上篇已經設計出比較完善的數據庫了,這篇開始進入代碼。 首先把上篇設計的數據庫腳本在數據庫中執行下,生成數據庫,然后在VS中建立項目,為了方便理解和查看,我設計的都是很直白的類名和文件名,沒有命名空間前綴。
采用接口方式,共8個項目:7個類庫和一個MVC項目, 分別為:
顯示層——MVC項目
業務邏輯層——訪問接口IBLL、具體實現BLL
數據訪問層——訪問接口IDAL、具體實現DAL
數據(模型)——DataModel
通用方法——Common
倉儲——Factory
這里的倉儲並不為了生產業務邏輯層和數據訪問層的接口,而是為了存放EntityFramework上下文對象和一些緩存管理,業務邏輯層和數據訪問層的接口生產(實現)工作我會交給Spring.NET注入實現。 框架搭建好之后如下:
框架搭建好了,接下去把數據庫添加進來,在DAL中(注意是DAL不是datamodel)添加新項,選擇數據--ADO.NET實體數據模型:
取個名字,就叫WeixinModel吧, 選擇從數據庫生成,配置一下數據庫連接到之前生成的數據庫,一路下一步,最后加載到edmx, 在edmx上右鍵--添加代碼生成項,選擇代碼:
選DbContext Generator, 然后保存一下edmx, 之后把edmx和weixinmodel.tt復制到DataModel,刪除DAL中的edmx和weixinmodel.tt, 在datamodel中打開weixinmodel.tt保存一下即可, 另外需要在DAL中保留的WeiXinModel.Context.cs中聲明datamodel命名空間。
框架和數據模型都有了,接下去在DAL、IDAL、BLL、IBLL中按照正確的引用層次添加引用,並寫幾個常用方法,就可以開始在顯示層中使用了,
這里舉例在DAL中寫添刪改查方法:

1 //添加 2 public T AddEntity<T>(DbContext db,T entity) where T : class 3 { 4 db.Entry<T>(entity).State = EntityState.Added; 5 db.SaveChanges(); 6 return entity; 7 } 8 9 //修改 10 public bool UpdateEntity<T>(DbContext db,T entity) where T : class 11 { 12 db.Set<T>().Attach(entity); 13 db.Entry<T>(entity).State = EntityState.Modified; 14 db.SaveChanges(); 15 return true; 16 } 17 //刪除 18 public bool DeleteEntity<T>(DbContext db,T entity) where T : class 19 { 20 db.Set<T>().Attach(entity); 21 db.Entry<T>(entity).State = EntityState.Deleted; 22 db.SaveChanges(); 23 return true; 24 25 } 26 27 28 29 30 // 返回一個對象 31 public T InfoEntities<T>(DbContext db, Expression<Func<T, bool>> whereLambda) where T : class 32 { 33 34 return db.Set<T>().Where<T>(whereLambda).FirstOrDefault(); 35 36 }
對應的把接口、業務邏輯層都寫上。
現在來到顯示層,默認的MVC項目是返回VIEW, 這里我們不需要返回頁面, 把home中的index改成Void返回類型, 接下去就是接收微信發來的請求進行判斷了,驗證請求----接收POST數據---分析XML----解析成自己想要的數據
入口:首先驗證消息來源是微信服務器,然后解析收到的xml,解析成功有數據則執行LookMsgType方法來進行處理

1 private IBLL.IDoWei BLLWei { set; get; } 2 public DbContext dbHome { get; set; } 3 private string token { get; set; } 4 Dictionary<string, string> xmlModel = new Dictionary<string, string>(); 5 public void Index() 6 { 7 dbHome=FContext.WeiXinDbContext(); 8 //xml字符串 9 string xmlData = string.Empty; 10 //請求類型 11 string method=Request.HttpMethod.ToLower(); 12 string signature = Request.QueryString["signature"]; 13 string timestamp = Request.QueryString["timestamp"]; 14 string nonce = Request.QueryString["nonce"]; 15 //驗證接入和每次請求驗證真實性 16 if (method == "get") 17 { 18 if (CheckSign(signature,timestamp,nonce)) 19 { 20 Often.ResponseToEnd(Request.QueryString["echostr"]); 21 } 22 else 23 { 24 Response.Status = "403"; 25 Often.ResponseToEnd(""); 26 } 27 } 28 //處理接收到的POST消息 29 else if (method == "post") 30 { 31 using (Stream stream = Request.InputStream) 32 { 33 Byte[] byteData = new Byte[stream.Length]; 34 stream.Read(byteData, 0, (Int32)stream.Length); 35 xmlData = Encoding.UTF8.GetString(byteData); 36 } 37 if (!string.IsNullOrEmpty(xmlData)) 38 { 39 try 40 { 41 xmlModel = ReadXml.GetXmlModel(xmlData); 42 } 43 catch 44 { 45 //未能正確處理 給微信服務器回復默認值 46 Often.ResponseToEnd(""); 47 } 48 } 49 if (xmlModel.Count > 0) 50 { 51 string msgType = ReadXml.ReadModel("MsgType", xmlModel); 52 LookMsgType(msgType); 53 } 54 } 55 else//除了post和get外 如head皆視為非法請求 56 { 57 Response.Status = "403"; 58 Often.ResponseToEnd(""); 59 } 60 dbHome.Dispose(); 61 }
這里用到的驗證方法:
1 /// <summary> 2 /// 驗證簽名 3 /// </summary> 4 /// <param name="signature"></param> 5 /// <param name="timestamp"></param> 6 /// <param name="nonce"></param> 7 /// <returns></returns> 8 public bool CheckSign(string signature, string timestamp, string nonce) 9 { 10 List<string> list = new List<string>(); 11 list.Add(token); 12 list.Add(timestamp); 13 list.Add(nonce); 14 //默認排序 15 list.Sort(); 16 string tmpStr = string.Empty; 17 list.All(l => { tmpStr += l; return true; }); 18 tmpStr = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); 19 //驗證 20 if (tmpStr == signature) 21 { 22 return true; 23 } 24 return false; 25 }
倉儲中的EF上下文:
1 public static DbContext WeiXinDbContext() 2 { 3 DbContext dbcontext =new WeiXinEntities(); //創建 4 dbcontext.Configuration.AutoDetectChangesEnabled = false;//自動檢測配置更改 5 dbcontext.Configuration.LazyLoadingEnabled = true;//延遲加載 6 dbcontext.Configuration.ValidateOnSaveEnabled = false;//自動跟蹤 7 return dbcontext; 8 }
Common中的解析微信發來的XML方法
1 //把接收到的XML轉為字典 2 public static Dictionary<string, string> GetXmlModel(string xmlStr) 3 { 4 XmlDocument doc = new XmlDocument(); 5 doc.LoadXml(xmlStr); 6 Dictionary<string, string> mo = new Dictionary<string, string>(); 7 var data = doc.DocumentElement.ChildNodes; 8 for (int i = 0; i < data.Count; i++) 9 { 10 mo.Add(data.Item(i).LocalName, data.Item(i).InnerText); 11 } 12 return mo; 13 } 14 15 16 17 ////從字典中讀取指定的值 18 public static string ReadModel(string key, Dictionary<string, string> model) 19 { 20 string str = ""; 21 model.TryGetValue(key, out str); 22 if (str== null) 23 str = ""; 24 return str; 25 }
好了,入口以及驗證相關的都解決了,下一篇開始微信消息處理LookMsgType方法實現