上篇已经设计出比较完善的数据库了,这篇开始进入代码。 首先把上篇设计的数据库脚本在数据库中执行下,生成数据库,然后在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 }
View Code
对应的把接口、业务逻辑层都写上。
现在来到显示层,默认的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 }
View Code
这里用到的验证方法:
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方法实现