微小黑開發筆記

一.說明javascript

  用c#基於.net 平臺的MVC框架開發的微網站。php

二.對象實體映射框架html

  1.Entity Framework:https://msdn.microsoft.com/en-us/library/jj592674(v=vs.113).aspx  CodeFirst技術java

    1.1經常使用的數據庫操做  git

using (var context = new BloggingContext()) 
{ 
    var blog = new Blog { Name = "ADO.NET Blog" }; 
    context.Entry(blog).State = EntityState.Added; 
    context.SaveChanges(); 
}
新增
var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" }; 
 
using (var context = new BloggingContext()) 
{ 
    context.Blogs.Attach(existingBlog); 
 
    // Do some more work...  
 
    context.SaveChanges(); 
}
修改

    1.2.建立數據庫    github

    [Serializable]
    [DataContract]
    [Table("WxStoreTB")]
    public class WxStoreTB : ModelBase
    {
        public WxStoreTB() {
            StoreBackground = "/Content/Images/adminbanner.jpg";
        }
        [DataMember]
        public string DistributorSlogan { get; set; }

        [DataMember]
        public string StoreLogo { get; set; }

        [DataMember]
        public string StoreBackground { get; set; }

        [DataMember]
        public string IndexBackgroundMusic { get; set; }

        [DataMember]
        public string EnglishName { get; set; }

        [DataMember]
        public string QRCodeImage { get; set; }

        [DataMember]
        /// <summary>
        /// 店鋪ID
        /// </summary>
        public int StoreTBID { get; set; }
    }
定義域模型    
    public class DbContextBase : DbContext, IDataRepository, IDisposable
    {
        public DbContextBase(string connectionString)
        {
            this.Database.Connection.ConnectionString = connectionString;
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }

        public DbContextBase(string connectionString, IAuditable auditLogger)
            : this(connectionString)
        {
            this.AuditLogger = auditLogger;
        }

        public IAuditable AuditLogger { get; set; }

        public T Update<T>(T entity, bool isSave = true) where T : ModelBase
        {
            var set = this.Set<T>();
            set.Attach(entity);
            this.Entry<T>(entity).State = EntityState.Modified;
            if (isSave)
            {
                this.SaveChanges();
            }
            return entity;
        }
封裝DbContext

    1.3對象關係映射:算法

      1.3.1Data Annotations:缺點是污染域模型    數據庫

    [DataContract]
    [Table("PageTB")]
    public class PageTB : ModelBase
    {

        /// <summary>
        ///店鋪ID
        /// </summary>
        [DataMember]
        [ForeignKey("StoreTB")]
        public int StoreTBID { get; set; }
        /// <summary>
        ///頁面類別 0:首頁 1:其餘
        /// </summary>
        [DataMember]
        public int PageType { get; set; }
        /// <summary>
        ///頁面名稱
        /// </summary>
        [DataMember]
        public string GuidNumber { get; set; }
        /// <summary>
        ///頁面路徑(站點根目錄爲起始的相對路徑)
        /// </summary>
        [DataMember]
        public string PagePath { get; set; }
        /// <summary>
        ///標題
        /// </summary>
        [DataMember]
        public string Title { get; set; }
        /// <summary>
        /// 是否已上架
        /// </summary>
        [DataMember]
        public bool IsOnShelf { get; set; }
        /// <summary>
        /// 版本號 空則放在商戶目錄下
        /// </summary>
        [DataMember]
        public string Version { get; set; }
    }
註解

      1.3.2Fluent API:      json

modelBuilder.Entity<BlogUser>().HasKey(user => user.UserId);
modelBuilder.Entity<BlogUser>().Property(user => user.BlogName).IsRequired();
View Code

 三.使用面向對象操做數據庫c#

  1.Sql  LinqSql LinqEntity

   例如:查詢Score表中至少有5名學生選修的並以3開頭的課程的平均分數。  

select avg(degree) from score where cno like '3%' group by Cno having count(*)>=5
Sql
        from s in Scores
        where s.CNO.StartsWith("3")
        group s by s.CNO
        into cc
        where cc.Count() >= 5
        select cc.Average( c => c.DEGREE)
LinqSql
 Scores.Where( s => s.CNO.StartsWith("3") )
            .GroupBy( s => s.CNO )
              .Where( cc => ( cc.Count() >= 5) )
                .Select( cc => cc.Average( c => c.DEGREE) )
LinqEntity

 四.路由

        protected void Application_Start() {
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            //定時任務
            JobManager.Initialize(new MyRegistry());

        }
註冊路由
    public class MobileAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Mobile";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "Mobile_default",
                "Mobile/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional },
                namespaces: new[] { "MiLai.Web.Admin.Areas.Mobile.Controllers" }
            );
        }
    }
設置路由規則

五.控制器 Controller  

  從controller獲取客戶端傳值的方式

  1. 從context object 直接提取

  2. 經過參數傳進來(由基類controller完成解析)

  3. 經過model binding

  

  context object經常使用的對象

Request.QueryString

從Get 請求的url中取

Request.Form

從Post請求的表單取

Request.Cookies

把值放在請求的cookie裏帶過來

RouteData.Route

從路由表裏取註冊的路由名

RouteData.Values

從路由表獲取路由配置的匿名對象

HttpContext.Cache

應用程序緩存

HttpContext.Items

存儲一些值,只在同一請求中使用(能夠在httppipeline過程的不一樣module,handler,以及頁面傳遞值)

HttpContext.Session

當前用戶的session

  

  經常使用的result:

ViewResult

返回一個view,能夠指定不一樣的controller

ParcialViewResult

返回部分view

RedirectToActionResult

轉到另外一個action

RedirectResult

返回301或者302(permanent)

JsonResult

返回js最喜歡的json,經常使用,尤爲當前段打算採用純js template,或者single page application

FileResult

文件result

ContentResult

字符串

HttpUnauthorizedResult

401,一般,會自動跳轉到登錄頁面

HttpNotFoundResult

404

六.Razor模板引擎(CSHTML)  

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
    var request = ViewData["request"] as CourseRequest;
    var categoryList = ViewData["categoryList"] as List<int>;
}
@using Qxun.Framework.Contract
@using Qxun.Framework.Utility
@using Qxun.Framework.Web.Controls
@using MiLai.Shop.Contract.Model
@model PagedList<CourseTB>

    <div class="row picListBox" id="albumContainer">
        @foreach (var item in Model)
        {   <!--圖片組件的邊框-->
            <div class="picModuleBox" id="picbox_1">

                <a data-fancybox-group="gallery" href="javascript:void 0;" onclick="videoplay('@item.MasterImage','@item.VedioPath')" title="a">
                    <img src="@item.MasterImage" />
                </a>
                <div class="overLay"></div>
                <h1> <span class="info" style=""><a id="remark_1">@item.Remark</a></span></h1>
                <div class="checkBox">
                    <input type="checkbox" name='ids' value='@item.ID' /><span id="title_1" class="itemName">@item.Title</span>
                </div>
                <div class="functionBox">
                    <a class="" href="@Url.Action("Edit", new { id = item.ID })">編輯</a>
                    <input id="1" type="text" class="InpSort" style=" width:35px; " value="11" />
                </div>
            </div>
        }
    </div>
視圖層CSHTML

 七.接入微信第三方

  微信公衆平臺:https://mp.weixin.qq.com/advanced/selfmenu?action=index&t=advanced/menu-setting&token=2122708442&lang=zh_CN

  微信測試公衆平臺:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

  開發文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

  1.基本配置

  

  

    設置的服務器地址url要能正確的響應微信服務器發送過來的請求,參考:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1434696670  

    public ActionResult Index(string signature, string timestamp, string nonce, string echostr,string encrypt_type, string msg_signature)
        {
            try
            {
                var token = CachedConfigContext.Current.WeixinConfig.Token;
                if (string.IsNullOrEmpty(token)) return Content("請先設置Token!");
                var ent = "";

                if (!BasicAPI.CheckSignature(signature, timestamp, nonce, token, out ent))
                {
                    LogHelper.WCInfo("CheckSignature:" + "CheckSignatureError");
                    return Content("參數錯誤!");
                }
                LogHelper.WCInfo("驗證經過");
                var streamReader = new StreamReader(Request.InputStream);
                var msg = streamReader.ReadToEnd();
                streamReader.Dispose();

                LogHelper.WCInfo("msg:" + msg);
                var decryptMsg = string.Empty;
                SortedDictionary<string, object> result = new SortedDictionary<string, object>();
                var wxBizMsgCrypt = new WXBizMsgCrypt(
                            CachedConfigContext.Current.WeixinConfig.Token,
                            CachedConfigContext.Current.WeixinConfig.EncodingAESKey,
                            CachedConfigContext.Current.WeixinConfig.AppID);
                var ret = wxBizMsgCrypt.DecryptMsg(msg_signature, timestamp, nonce, msg, ref decryptMsg);
                LogHelper.WCInfo("ret:" + ret);
                if (ret == 0)
                {
                    result = DataConvertHelper.FromXml(decryptMsg);
                    foreach (var item in result)
                    {
                        LogHelper.WCInfo(string.Format("微信預受權方面的推送信息:key={0} => value={1}", item.Key, item.Value));
                    }
                    string openID = (string)result["FromUserName"];
                    WxUserTB fromWxUser = ServiceContext.Current.HuiXianUserService.GetWxUser(u => u.OpenId == openID);
                    if (result.ContainsKey("EventKey") && fromWxUser != null)
                    {
                        int menuID = 0;
                        try
                        {
                            menuID = Convert.ToInt32(result["EventKey"]);
                        }
                        catch (Exception e)
                        {
                            LogHelper.WCInfo(e.Message);
                        }
                        if (menuID > 0)
                        {
                            var setting = ServiceContext.Current.HuiXianCmsService.GetWxSetting();
                            WeixinMenuTB weixinMenu = ServiceContext.Current.WeixinService.GetWeixinMenu(menuID);
                           
                            if (weixinMenu != null)
                            {
                                if (weixinMenu.MaterialID > 0)
                                {
                                    WeixinMaterialTB weixinMaterial = ServiceContext.Current.WeixinMaterialService.GetMaterial(weixinMenu.MaterialID);
                                    if (weixinMaterial != null)
                                    {

                                        if (!string.IsNullOrEmpty(weixinMaterial.MediaId))
                                        {
                                            WeixinMaterialSubTB weixinMaterialSub = ServiceContext.Current.WeixinMaterialService.GetFirstMaterialSub(weixinMaterial.ID);
                                            if (weixinMenu.Type == "click")
                                            {
                                                //微信菜單點擊後被動回覆圖文消息
                                                WeixinNews news = new WeixinNews
                                                {
                                                    picurl =CachedConfigContext.Current.WeixinConfig.Domain+ weixinMaterialSub.ImageUrl,
                                                    title = weixinMaterialSub.Title,
                                                    description = weixinMaterialSub.Content,
                                                    url = weixinMaterialSub.Url
                                                };
                                                string repayResult = ReplayPassiveMessageAPI.RepayNews(fromWxUser.OpenId, "gh_117ef9c5cdee", news);
                                                LogHelper.WCInfo("repayResult:" + repayResult);
                                                return Content(repayResult);
                                            }
                                        }
                                        else
                                        {
                                            LogHelper.WCInfo("微信素材還沒有上傳至微信服務器");
                                        }

                                    }
                                    else
                                    {
                                        LogHelper.WCInfo("微信素材不存在");
                                    }
                                }
                                else
                                {
                              
                                    //若是菜單未關聯素材 默認就發微信二維碼
                                    if (string.IsNullOrEmpty(fromWxUser.media_id))
                                    {                                                                
                                        fromWxUser.QRCode= ServiceContext.Current.HuiXianUserService.GetWxUserQRCode(fromWxUser);
                                        LogHelper.WCInfo("QRCode:" + fromWxUser.QRCode);
                                    }
                                    string imgurl = CachedConfigContext.Current.WeixinConfig.Domain + fromWxUser.QRCode;
                                    WebRequest request = HttpWebRequest.Create(imgurl);
                                    var response = request.GetResponse();
                                    Stream stream = response.GetResponseStream();
                                    int pos = imgurl.LastIndexOf("/");
                                    string fileName = imgurl.Substring(pos + 1);
                                    LogHelper.WCInfo("fileName:" + fileName);
                                    ResultData ResultData = MaterialAPI.AddMaterial(setting.AccessToken, "image", fileName, stream);
                                    LogHelper.WCInfo("ResultData:" + JsonConvert.SerializeObject(ResultData));

                                    string media_id = (string)ResultData.media_id;
                                    LogHelper.WCInfo("media_id:" + media_id);
                                    if (!string.IsNullOrEmpty(media_id))
                                    {
                                        fromWxUser.media_id = media_id;
                                        ServiceContext.Current.HuiXianUserService.UpdateWxUser(fromWxUser);
                                        string repayResult = ReplayPassiveMessageAPI.ReplayImage(fromWxUser.OpenId, "gh_117ef9c5cdee", media_id);
                                        return Content(repayResult);
                                    }

                                }
                            }
                            else
                            {
                                LogHelper.WCInfo("微信菜單不存在");
                            }
                        }
                        else
                        {
                            LogHelper.WCInfo("菜單不存在");
                        }
                    }
                }
                LogHelper.WCInfo("END");
               
            }
            catch (Exception e)
            {
                LogHelper.WCInfo(e.Message);
            }
            return Content(echostr); //返回隨機字符串則表示驗證經過

        }
實例代碼

    1.獲取access_token(調用接口的令牌)  https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

      1.1 第三方程序集 定時任務執行器 FluentScheduler  :https://github.com/fluentscheduler/FluentScheduler

      1.2調用接口獲取access_token       

        public static dynamic GetAccessToken(string appid, string secrect)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", "client_credential", appid, secrect);
            var client = new HttpClient();
            var result = client.GetAsync(url).Result;
            if (!result.IsSuccessStatusCode) return string.Empty;
            var token = DynamicJson.Parse(result.Content.ReadAsStringAsync().Result);
            return token;
        }
View Code

    2.用戶自定義菜單 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013

    3.新增素材 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1494572718_WzHIY    

        public static ResultData AddNews(string access_token, List<WeixinArtcle> articles)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/material/add_news?access_token={0}", access_token);
            var client = new HttpClient();
            var atrticle = DynamicJson.Serialize(articles);
            var builder = new StringBuilder();
            builder
                .Append("{")
                .Append('"' + "articles" + '"' + ":").Append(atrticle)
                .Append("}");
            var result = client.PostAsync(url, new StringContent(builder.ToString())).Result;


            if (!result.IsSuccessStatusCode) return null;
            else { return DynamicJson.Parse(result.Content.ReadAsStringAsync().Result); }
        }
新增素材

    4.模板消息 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277

    5.網頁受權 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842    

        public ActionResult OAuth(string state)
        {


            this.WxUserCookie = "";
            var domain = CachedConfigContext.Current.WeixinConfig.Domain;
            var appId = CachedConfigContext.Current.WeixinConfig.AppID;
            var redirect_uri = System.Web.HttpUtility.UrlEncode(string.Format("{0}/Mobile/WCUser/Callback", domain));
            LogHelper.WCInfo(string.Format("微信受權redirect_uri:{0}/Mobile/WCUser/Callback", domain));
            var weixinOAuth2Url = string.Format(
                            "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state={3}#wechat_redirect",
                  appId, redirect_uri, "snsapi_userinfo", state);
            LogHelper.WCInfo("微信受權weixinOAuth2Url:" + weixinOAuth2Url);
            return Redirect(weixinOAuth2Url);
        }
View Code

      5.1網頁受權回調

      用戶贊成受權後頁面將跳轉至 redirect_uri/?code=CODE&state=STATE

      5.2獲取網頁受權access_token      

        public static dynamic GetAccessToken(string code, string appId, string appSecret)
        {
            var client = new HttpClient();
            var result = client.GetAsync(string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", appId, appSecret, code)).Result;
            if (!result.IsSuccessStatusCode) return null;
            return DynamicJson.Parse(result.Content.ReadAsStringAsync().Result);
        }
View Code

      5.3拉取用戶信息        

        public static dynamic GetUserInfo(string accessToekn, string openId, string lang = "zh_CN")
        {
            var client = new HttpClient();
            var result = client.GetAsync(string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang={2}", accessToekn, openId, lang)).Result;
            if (!result.IsSuccessStatusCode) return null;
            return DynamicJson.Parse(result.Content.ReadAsStringAsync().Result);
        }
View Code

    6.JS-SDK  https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

      6.1獲取jsapi_ticket      

        public static dynamic GetTickect(string access_token)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", access_token);
            var client = new HttpClient();
            var result = client.GetAsync(url).Result;
            if (!result.IsSuccessStatusCode) return string.Empty;
            var jsTicket = DynamicJson.Parse(result.Content.ReadAsStringAsync().Result);
            return jsTicket;
        }
View Code

      6.2簽名算法      

        public static string GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url, out string string1)
        {
            var string1Builder = new StringBuilder();
            string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
                          .Append("noncestr=").Append(noncestr).Append("&")
                          .Append("timestamp=").Append(timestamp).Append("&")
                          .Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);
            string1 = string1Builder.ToString();
            return Util.Sha1(string1);


        public static string Sha1(string orgStr, string encode = "UTF-8")
        {
            var sha1 = new SHA1Managed();
            var sha1bytes = System.Text.Encoding.GetEncoding(encode).GetBytes(orgStr);
            byte[] resultHash = sha1.ComputeHash(sha1bytes);
            string sha1String = BitConverter.ToString(resultHash).ToLower();
            sha1String = sha1String.Replace("-", "");
            return sha1String;
        }
View Code

      6.3建立JSSDK對象    

        public static JSSDKModel GetJsSdk(string ticket,string appID,string requestUrl,string shareUrl,string shareImg,string title,string shareDesc)
        {
            var nonceStr = Guid.NewGuid().ToString("N");
            string message = "";
            var timeStamp = DateTimeHelper.DateTimeToUnixTimestamp(DateTime.Now);
            var signature = JSAPI.GetSignature(ticket, nonceStr, timeStamp, requestUrl, out message);
            var model = new JSSDKModel()
            {
                appId = appID,
                nonceStr = nonceStr,
                signature = signature,
                timestamp = timeStamp,
                jsapiTicket = ticket,
                shareUrl =shareUrl,
                shareImg = shareImg,
                title = title,
                desc = shareDesc
            };
            return model;
        }
View Code

      6.4嵌入js腳本      

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript"></script>
<script>
(function(){
    wx.config({
    debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。
    appId: '', // 必填,公衆號的惟一標識
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機串
    signature: '',// 必填,簽名,見附錄1
    jsApiList: [] // 必填,須要使用的JS接口列表,全部JS接口列表見附錄2
});

    wx.ready(function(){
    execute();
    // config信息驗證後會執行ready方法,全部接口調用都必須在config接口得到結果以後,config是一個客戶端的異步操做,因此若是須要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。對於用戶觸發時才調用的接口,則能夠直接調用,不須要放在ready函數中。
});
})()

function execute() {
            var title = "@ViewBag.JSSDK.title"; // 分享標題
            var link = '@Server.UrlDecode(ViewBag.JSSDK.shareUrl)'; // 分享連接
            var imgUrl = '@ViewBag.JSSDK.shareImg'; // 分享圖標
            var desc = "@ViewBag.JSSDK.desc"; // 分享描述
            wxJs.showmenu();
            //朋友圈
            wxJs.onMenuShareAppMessage({ title: title, link: link, imgUrl: imgUrl, desc: desc, ok: function () {
                //分享成功後,增長分享記錄
                jsprint("分享成功", "", "success");

            }, cancel: function () {
                jsprint("分享取消", "", "error");
  
            }
            });
            //轉發給朋友的
            wxJs.onMenuShareTimeline({ title: title, link: link, imgUrl: imgUrl, ok: function () {
               
                jsprint("分享成功", "", "success");

            }, cancel: function () {

                jsprint("分享取消", "", "error");
            }
            });

            //var latitude = 0;
            //var longitude = 0;
            //wx.getLocation({
            //    success: function (res) {
            //        //獲取經緯度數值   按照,分割字符串 取出前兩位 解析成浮點數
            //        latitude=res.latitude;
            //        longitude=res.longitude;


            //    },
            //    cancel: function (res) {
            //        alert('用戶拒絕受權獲取地理位置');
            //    }
            //});

            //wx.openLocation({
            //    latitude: latitude,
            //    longitude: longitude,
            //    name: '測試地址',
            //    address: '廣州市海珠區新港中路 397 號',
            //    scale: 14,
            //    infoUrl: 'http://weixin.qq.com'
            //});
        })
</script>
View Code

     7.微信支付 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

相關文章
相關標籤/搜索