做网页的时候,水煮大神结局是什么们经常命名为index,或者demo,或者default,这些页面都分别是什么意思啊

上一篇已经搭建好整体框架,实现了入口的验证, 验证通过后就交给LookMsgType方法处理,LookMsgType方法主要是对微信发来的不同的消息进行分解,不同的类型交给业务逻辑层不同的方法处理, 对不同类型的消息判断,可以用if,也可以用switch 一般来说超过5个的if用switch会更好, 这里贴出LookMsgType方法:
public void LookMsgType(string msgType)
#region 判断消息类型
switch (msgType)
case &text&:
RText mText = new RText();
mText = ReadXml.GetModel(mText, xmlModel);
BLLWei.DoText(dbHome, mText);//文本消息
case &image&:
RImg mImg = new RImg();
mImg = ReadXml.GetModel(mImg, xmlModel);
BLLWei.DoImg(dbHome,mImg);//图片
case &voice&: //声音
RVoice mVoice = new RVoice();
mVoice = ReadXml.GetModel(mVoice, xmlModel);
BLLWei.DoVoice(dbHome,mVoice);
case &video&://视频
RVideo mVideo = new RVideo();
mVideo = ReadXml.GetModel(mVideo, xmlModel);
BLLWei.DoVideo(dbHome, mVideo);
case &location&://地理位置
RLocation mLocation = new RLocation();
mLocation = ReadXml.GetModel(mLocation, xmlModel);
BLLWei.DoLocation(dbHome,mLocation);
case &link&://链接
RLink mLink = new RLink();
mLink = ReadXml.GetModel(mLink, xmlModel);
BLLWei.DoLink(dbHome,mLink);
#region 事件
case &event&:
switch (ReadXml.ReadModel(&Event&, xmlModel))
case &subscribe&:
if (ReadXml.ReadModel(&EventKey&, xmlModel).IndexOf(&qrscene_&) &= 0)
RCodeNotSub mNotSub = new RCodeNotSub();
mNotSub = ReadXml.GetModel(mNotSub, xmlModel);
BLLWei.DoCodeNotSub(dbHome,mNotSub);//未关注的新用户,扫描带参数的二维码关注
RSub mSub = new RSub();
mSub = ReadXml.GetModel(mSub, xmlModel);
BLLWei.DoSub(dbHome,mSub);//普通关注
case &unsubscribe&:
RUnsub mUnSub = new RUnsub ();
mUnSub = ReadXml.GetModel(mUnSub, xmlModel);
BLLWei.DoUnSub(dbHome,mUnSub);//取消关注
case &SCAN&:
RCodeSub mCodeSub = new RCodeSub();
mCodeSub = ReadXml.GetModel(mCodeSub, xmlModel);
BLLWei.DoCodeSub(dbHome,mCodeSub);//已经关注的用户扫描带参数的二维码
case &LOCATION&://用户上报地理位置
RSubLocation mSubLoc = new RSubLocation();
mSubLoc = ReadXml.GetModel(mSubLoc, xmlModel);
BLLWei.DoSubLocation(dbHome, mSubLoc);
case &CLICK&://自定义菜单点击
RMenuClick mMenuClk = new RMenuClick();
mMenuClk = ReadXml.GetModel(mMenuClk, xmlModel);
BLLWei.DoMenuClick(dbHome, mMenuClk);
case &VIEW&://自定义菜单跳转事件
RMenuView mMenuVw = new RMenuView();
mMenuVw = ReadXml.GetModel(mMenuVw, xmlModel);
BLLWei.DoMenuView(dbHome, mMenuVw);
#endregion
#endregion
外层switch判断msgtype,
在event类型时,再次switch判断具体的事件类型(关注、取消关注、自定义菜单事件等),
至此所有的微信发来的消息都有处理了,在上面代码中用到消息模型以及ReadXml.GetModel方法给模型赋值, 赋值之后传递给业务逻辑层对应的方法处理,
下面写出消息封装和给模型赋值的方法。
1、消息封装:
对所有微信发来的消息进行封装, 在datamodel中建一个Receive文件夹和一个send文件夹,在其中分别建立对应消息的类,完成之后,完整的datamodel类库如下图:
—–接收消息:
文本消息RText.cs
public class RText
public string ToUserName { }// 开发者微信号
public string FromUserName { }// 用户号(OpenID)
public long CreateTime { }// 创建时间
public string MsgType { } //消息类型
public string Content { }//内容
public long MsgId { }//消息ID
自定义菜单点击RMenuClick.cs
public class RMenuClick
public string ToUserName { }// 开发者微信号
public string FromUserName { }// 用户号(OpenID)
public long CreateTime { }// 创建时间
public string MsgType { } //消息类型
public string Event { }//事件类型
public string EventKey { }//事件key
其他也都类似,不一一列举。
—–发送消息
发送文本消息SText.cs
public class SText
public string ToUserName { }// 用户号(OpenID)
public string FromUserName { }// 开发者微信号
public long CreateTime { }// 创建时间
public string MsgType { get { return &text&; } } //消息类型
public string Content { }//内容
发送图文消息SNews.cs
namespace DataModel.Send
public class SNews
public string ToUserName { }// 用户号(OpenID)
public string FromUserName { }// 开发者微信号
public long CreateTime { }// 创建时间
public string MsgType { get { return &news&; } } //消息类型
public int ArticleCount { }//图文个数
public List&ArticlesModel& Articles { }//图文列表
public class ArticlesModel //默认第一条大图显示
public string Title { }//标题
public string Description { }//描述
public string PicUrl { }//图片链接
public string Url { }//点击之后跳转的链接
发送图文消息
在发送图文消息中,因为回复给微信的图文消息中,具体的图文内容是多条(最多可以10条),所以单独会有ArticlesModel。
后面文章会写出图文消息的发送。
2、通过反射给model赋值
在上篇文章写的入口处,已经有了解析xml的方法,现在封装了消息,通常的做法,是每次用到对应的model就手动写代码赋值,
而我这里LookMsgType方法中所有给消息赋值时全用的ReadXml.GetModel这同一个方法,
这里用的就是反射,方法如下:
/// &summary&
/// 通过反射给接收消息model赋值
/// &/summary&
/// &typeparam name=&T&&&/typeparam&
/// &param name=&model&&&/param&
/// &returns&&/returns&
public static T GetModel&T&(T model, Dictionary&string, string& xmlModel) where T : class
var m = model.GetType();
foreach (PropertyInfo p in m.GetProperties())
string name = p.N
if (xmlModel.Keys.Contains(name))
string value=xmlModel.Where(x =& x.Key == name).FirstOrDefault().V
p.SetValue(model,
string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, p.PropertyType), null);
T model 就是要使用的消息类,
xmlmodel是在入口处传递进来的解析的微信发来的xml信息,
这样,就不需要每次手动写代码赋值了。
好了,此篇实现了lookmsgtype方法, 实现了消息封装和反射赋值, 接下去就是到了业务逻辑层中的处理和具体实现了..
上篇已经设计出比较完善的数据库了,这篇开始进入代码。
首先把上篇设计的数据库脚本在数据库中执行下,生成数据库,然后在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中写添删改查方法:
public T AddEntity&T&(DbContext db,T entity) where T : class
db.Entry&T&(entity).State = EntityState.A
db.SaveChanges();
public bool UpdateEntity&T&(DbContext db,T entity) where T : class
db.Set&T&().Attach(entity);
db.Entry&T&(entity).State = EntityState.M
db.SaveChanges();
public bool DeleteEntity&T&(DbContext db,T entity) where T : class
db.Set&T&().Attach(entity);
db.Entry&T&(entity).State = EntityState.D
db.SaveChanges();
// 返回一个对象
public T InfoEntities&T&(DbContext db, Expression&Func&T, bool&& whereLambda) where T : class
return db.Set&T&().Where&T&(whereLambda).FirstOrDefault();
对应的把接口、业务逻辑层都写上。
现在来到显示层,默认的MVC项目是返回VIEW, 这里我们不需要返回页面, 把home中的index改成Void返回类型, 接下去就是接收微信发来的请求进行判断了,验证请求—-接收POST数据—分析XML—-解析成自己想要的数据
  入口:首先验证消息来源是微信服务器,然后解析收到的xml,解析成功有数据则执行LookMsgType方法来进行处理
private IBLL.IDoWei BLLWei { }
public DbContext dbHome { }
private string token { }
Dictionary&string, string& xmlModel = new Dictionary&string, string&();
public void Index()
dbHome=FContext.WeiXinDbContext();
//xml字符串
string xmlData = string.E
//请求类型
string method=Request.HttpMethod.ToLower();
string signature = Request.QueryString[&signature&];
string timestamp = Request.QueryString[&timestamp&];
string nonce = Request.QueryString[&nonce&];
//验证接入和每次请求验证真实性
if (method == &get&)
if (CheckSign(signature,timestamp,nonce))
Often.ResponseToEnd(Request.QueryString[&echostr&]);
Response.Status = &403&;
Often.ResponseToEnd(&&);
//处理接收到的POST消息
else if (method == &post&)
using (Stream stream = Request.InputStream)
Byte[] byteData = new Byte[stream.Length];
stream.Read(byteData, 0, (Int32)stream.Length);
xmlData = Encoding.UTF8.GetString(byteData);
if (!string.IsNullOrEmpty(xmlData))
xmlModel = ReadXml.GetXmlModel(xmlData);
//未能正确处理 给微信服务器回复默认值
Often.ResponseToEnd(&&);
if (xmlModel.Count & 0)
string msgType = ReadXml.ReadModel(&MsgType&, xmlModel);
LookMsgType(msgType);
else//除了post和get外 如head皆视为非法请求
Response.Status = &403&;
Often.ResponseToEnd(&&);
dbHome.Dispose();
这里用到的验证方法:
/// &summary&
/// 验证签名
/// &/summary&
/// &param name=&signature&&&/param&
/// &param name=&timestamp&&&/param&
/// &param name=&nonce&&&/param&
/// &returns&&/returns&
public bool CheckSign(string signature, string timestamp, string nonce)
List&string& list = new List&string&();
list.Add(token);
list.Add(timestamp);
list.Add(nonce);
//默认排序
list.Sort();
string tmpStr = string.E
list.All(l =& { tmpStr += });
tmpStr = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, &SHA1&);
if (tmpStr == signature)
仓储中的EF上下文:
public static DbContext WeiXinDbContext()
DbContext dbcontext =new WeiXinEntities();
dbcontext.Configuration.AutoDetectChangesEnabled =//自动检测配置更改
dbcontext.Configuration.LazyLoadingEnabled =//延迟加载
dbcontext.Configuration.ValidateOnSaveEnabled =//自动跟踪
Common中的解析微信发来的XML方法
//把接收到的XML转为字典
public static Dictionary&string, string& GetXmlModel(string xmlStr)
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
Dictionary&string, string& mo = new Dictionary&string, string&();
var data = doc.DocumentElement.ChildN
for (int i = 0; i & data.C i++)
mo.Add(data.Item(i).LocalName, data.Item(i).InnerText);
////从字典中读取指定的值
public static string ReadModel(string key, Dictionary&string, string& model)
string str = &&;
model.TryGetValue(key, out str);
if (str== null)
开发微信公众平台之前,先去微信官方了解下大概的情况 这里: ;看了之后心里大致有数了,开始设计数据库,尽可能的考虑,未考虑到的,以后再补充。
1、首先是用户部分,根据微信官方的接口结合实际运用,用户部分有3个表:用户表、用户资料表、用户分组表,我设计的如下:
2、用户设计好之后就是文章部分,包括:文章分类表、文章表,
设计如下:
3、有了用户相关的表我们可以保存用户,有了文章模块的表我们可以根据用户输入的信息查询文章进行返回(返回文本、图文、图片、音乐、视频、语音等 等),但是实际运用中,我们存在需要指定特定的关键字返回特定的内容的情况,那么就需要专门的特定关键字模块,
包括:关键字表、关键字返回的内容表,
这里的内容表看着像是与上面的文章表有重合,实则不然, 这里是特定关键字指定的回复内容,可以指定返回文本、图文或其他多媒体信息,当返回多媒体信息时内容中存入文件地址,
上面的文章表是标准的通用的文章内容表, 供用户查询多数情况下直接返回图文信息,且图文信息点击链接时就是这篇文章对应的展示地址, 相当于一个微,
所以文章和这个关键字的内容表分开设计更加方便管理。
设计如下:
4、消息记录,
把用户发来的消息进行记录,方便后续处理,
比如 根据用户上次发来的事件消息,之后再发同一个关键词时,返回对应菜单下的内容,而不用用户每次发送消息都带对应的菜单选项;客服消息根据记录的信息做个性 化的服务 等等。
包括:用户发来的消息记录表、回复给用户的消息记录表
,有了这些可以完整的还原和用户的对话,这里是记录和用户交流的过程,具体用户发来的消息需要返回什么样的消息,由项目代码中业务决定。
设计如下:
5、自定义菜单,创建和管理微信公众平台中的自定义菜单,设计如下:
具体根据做的实际项目来设计, 比如 用户分析、访问统计;
用户积分;
二维码相关 等等 ,
此处先不设计。
以上设计中,有一些是没有设计到数据库的, 比如关键字模块中的回复消息类型、消息记录中的消息类型,
这些固定不变(由腾讯决定)的少量的单选项形式的数据,我们在具体项目中使用其他方法来实现(固定静态、配置文件、缓存等),无需设计数据库。
完整设计如下:(为了方便截图 ,我把各个模块的表拖动覆盖了)
下载脚本,如下:在数据库中创建一个名为微信(设计数据库时自己定义的)的数据库,脚本执行一下就OK,
weixin -------微信公众平台
if exists ( select *
sysobjects where name = 'tb_User' and xtype='U')
drop table tb_User
create table
tb_User------------------------------------------------------------用户表
primary key identity(1,1)
NOT NULL , --主键-主键
NOT NULL , --自有系统的用户ID
varchar(150)
default ''
NOT NULL , --微信openid
NOT NULL , --分组ID
varchar(50)
default ''
NOT NULL , --昵称-微信
CreateTime
NOT NULL , --创建时间
NOT NULL , --状态-1为正常
varchar(150)
default ''
NOT NULL , --预留字段1
if exists ( select *
sysobjects where name = 'tb_Group' and xtype='U')
drop table tb_Group
create table
tb_Group-----------------------------------------------------------分组表
primary key identity(1,1)
NOT NULL , --主键-主键
varchar(50)
default ''
NOT NULL , --名称-本地
NOT NULL , --对应微信分组ID
varchar(50)
default ''
NOT NULL , --微信分组名
varchar(100)
default ''
NOT NULL , --备注
CreateTime
NOT NULL , --创建时间
NOT NULL , --状态
if exists ( select *
sysobjects where name = 'tb_UserData' and xtype='U')
drop table tb_UserData
create table
tb_UserData--------------------------------------------------------用户资料表
primary key identity(1,1)
NOT NULL , --主键-主键
NOT NULL , --用户表主键
NOT NULL , --性别0未知1男2女
varchar(20)
default ''
NOT NULL , --城市
varchar(30)
default ''
NOT NULL , --国家
varchar(20)
default ''
NOT NULL , --省份
varchar(15)
default ''
NOT NULL , --语言
HeadImgUrl
varchar(250)
default ''
NOT NULL , --用户头像
varchar(50)
default ''
NOT NULL , --最后次关注时间戳
CreateTime
NOT NULL , --创建时间
NOT NULL , --状态
varchar(150)
default ''
NOT NULL , --预留1
if exists ( select *
sysobjects where name = 'tb_Article' and xtype='U')
drop table tb_Article
create table
tb_Article---------------------------------------------------------文章表
primary key identity(1,1)
NOT NULL , --主键-主键
NOT NULL , --类别ID
NOT NULL , --置顶0不1是
TopBeginTime
NOT NULL , --置顶开始时间
TopEndTime
NOT NULL , --置顶结束时间
varchar(100)
default ''
NOT NULL , --标题
varchar(150)
default ''
NOT NULL , --关键字
varchar(680)
default ''
NOT NULL , --简介//680为微信文字上限左右
default ''
NOT NULL , --内容
varchar(50)
'独家原创'
NOT NULL , --来源
CreateTime
NOT NULL , --创建时间
PublishTime
NOT NULL , --发布时间
NOT NULL , --排序
NOT NULL , --状态
varchar(350)
default ''
NOT NULL , --缩略图
if exists ( select *
sysobjects where name = 'tb_ArtSort' and xtype='U')
drop table tb_ArtSort
create table
tb_ArtSort---------------------------------------------------------文章分类表
primary key identity(1,1)
NOT NULL , --主键-主键
varchar(50)
default ''
NOT NULL , --名称
NOT NULL , --父级ID
IndexLevel
NOT NULL , --当前级别
NOT NULL , --排序
NOT NULL , --状态
varchar(150)
default ''
NOT NULL , --备注
if exists ( select *
sysobjects where name = 'tb_KeyWord' and xtype='U')
drop table tb_KeyWord
create table
tb_KeyWord---------------------------------------------------------关键字表
primary key identity(1,1)
NOT NULL , --主键-主键
varchar(50)
default ''
NOT NULL , --名称
varchar(250)
default ''
NOT NULL , --备注
NOT NULL , --状态
CreateTime
NOT NULL , --创建时间
NOT NULL , --回复消息类型1为文本
if exists ( select *
sysobjects where name = 'tb_KeyContent' and xtype='U')
drop table tb_KeyContent
create table
tb_KeyContent------------------------------------------------------关键字返回内容表
primary key identity(1,1)
NOT NULL , --主键-主键
varchar(150)
default ''
NOT NULL , --标题
varchar(700)
default ''
NOT NULL , --内容
NOT NULL , --关键字ID
NOT NULL , --类型-文本图文等
varchar(250)
default ''
NOT NULL , --图片
NOT NULL , --置顶
TopBeginTime
NOT NULL , --置顶开始时间
TopEndTime
NOT NULL , --置顶结束时间
CreateTime
NOT NULL , --创建时间
NOT NULL , --状态
varchar(250)
NOT NULL , --图文时点开的链接
if exists ( select *
sysobjects where name = 'tb_UserMsg' and xtype='U')
drop table tb_UserMsg
create table
tb_UserMsg---------------------------------------------------------用户消息记录表
primary key identity(1,1)
NOT NULL , --主键-主键
NOT NULL , --消息类型文本、事件
NOT NULL , --事件ID//自定义菜单的ID
varchar(700)
default ''
NOT NULL , --消息内容
CreateTime
NOT NULL , --创建时间
NOT NULL , --状态
NOT NULL , --回复状态
varchar(50)
default ''
NOT NULL , --微信消息ID
NOT NULL , --用户表主键
if exists ( select *
sysobjects where name = 'tb_245' and xtype='U')
drop table tb_245
create table
tb_245-------------------------------------------------------------回复消息表
primary key identity(1,1)
NOT NULL , --主键-主键
NOT NULL , --用户表主键
NOT NULL , --消息表主键
NOT NULL , --回复类型//文本图文
NOT NULL , --回复点//1文章2关键词
ReContentId
varchar(80)
NOT NULL , --回复的内容ID串
CreateTime
NOT NULL , --回复记录时间
if exists ( select *
sysobjects where name = 'tb_PersonalMenu' and xtype='U')
drop table tb_PersonalMenu
create table
tb_PersonalMenu----------------------------------------------------自定义菜单表
primary key identity(1,1)
NOT NULL , --主键-主键
varchar(50)
default ''
NOT NULL , --名称
NOT NULL , --类型1click2view
NOT NULL , --父级ID
IndexLevel
NOT NULL , --当前级别
varchar(350)
NOT NULL , --链接地址view时用
CreateTime
NOT NULL , --创建时间
NOT NULL , --排序
NOT NULL , --状态
varchar(150)
default ''
NOT NULL , --备注
上篇已经成功响应了关注事件,也实现了文本消息的发送,这篇开始图文消息处理, 微信中最常用的消息类型就是图文消息了,因为它图文并茂,最能表达信息。 图文消息在微信中的接口定义如下:
&![CDATA[toUser]]&
&![CDATA[fromUser]]&
&![CDATA[news]]&
&![CDATA[title1]]&
&![CDATA[description1]]&
&![CDATA[picurl]]& &![CDATA[url]]&
&![CDATA[title]]&
&![CDATA[description]]&
&![CDATA[picurl]]& &![CDATA[url]]&
加上文字定义:
很多人第一次看这个文档时会感觉看不懂,
因为它这写的实在是不太直观,
多看几眼就明白了,
开发者、用户、时间等等跟文本消息及其他消息都一样, 唯一不一样的是图文消息中articles节点又是个多条记录的节点,它跟其他节点同级,具体文章相当于子级,
这个看了之前文章中定义图文消息模型就很直观了,我把文章单独作为一个list当作图文消息模型中的一个属性来用。
我们这里模拟几条数据
SNews mN = new SNews();
mN.FromUserName = ReadXml.ReadModel(&ToUserName&, model);
mN.ToUserName = ReadXml.ReadModel(&FromUserName&, model);
mN.CreateTime = long.Parse(ReadXml.ReadModel(&CreateTime&, model));
mN.MsgType = &news&;
// 以下为文章内容, 实际使用时,此处应该是一个跟数据库交互的方法,查询出文章
//文章条数, 文章内容等 都应该由数据库查询出来的数据决定 这里测试,就模拟几条
mN.ArticleCount =5;
List listNews = new List();
for (int i = 0; i & 6;i++ )
ArticlesModel ma = new ArticlesModel();
ma.Title =&这是第&+i.ToString()+&篇文章&;
ma.Description =&--&+i.ToString()+&--&;
ma.PicUrl = &/pic/wallpaper/dongwu/taipingniaogaoqingbizhi/s00&+(i+1).ToString()+&.jpg&;
ma.Url = &/mochen/&;
listNews.Add(ma);
mN.Articles = listN
ReadXml.ResponseToEnd(DALWei.SendNews(mN));
demo是输入?或?或帮助
回复文字菜单, 输入其他字符回复图文
图文消息超过1篇时默认第一篇是大图显示,且每一篇都仅仅显示标题,
当只有一条时会显示简介,如图:
无论有多少条文章,每篇文章点击都会打开所赋值的文章链接, 此时就相当于打开了一个浏览器访问你的web页面,这个页面你可以自行设计成任何样子,
由于手机大小不一,这个页面设计时最好考虑下屏幕适配,做成响应式布局吧
好了,图文消息就是这么多,至此为止,微信所有的基础内容基本上都完成了,
在第7篇我会放出完整的demo版源码,保证拿回去扔到服务器上指定个域名,然后到微信官方填写一下,立刻就能看到效果……
目录索引:
说起.NET Gadgeteer,不得不先说一下.NET Micro Framework,虽然.NET Micro Framework已经有十几年的发展历史了,但是在全球范围内,.NET Micro Framework的知名度,远远低于它的近亲.NET Framework和.NET Compact Framework,其原因值得探究。
.NET Micro Framework仅从名字上理解,就是一个框架,和.NET Framework还有.NET Compact Framework应该没有什么大的不同,但是.NET Micro Framework有自己的特色,就是自启动功能,也就是不需要操作系统也能运行。这个特色将.NET Micro Framework逐渐演化为一个操作系统的角色。恰是这一点,在.NET Micro Framework早期发展过程中,越来越显得没有优势和特色。
早期的.NET Micro Framework并没有直接对第三方开放,而是作为微软.NET全战略的一环,以.NET Micro Framework为基础,推出一系列产品。目前比较火热的可穿戴设备,比如智能手表。其实.NET Micro Framework为核心的第一代产品就是智能手表,早在2003年的拉斯维加斯的Comdex贸易展上,比尔盖茨就曾亲自戴着智能手表进行过推广。这项 以.NET Micro Framework为核心发展起来的技术叫MSN Direct,除了手表产品外,还有可以预报天气的咖啡壶,GPS导航器等产品。
以.NET Micro Framework为核心的第二代产品是SideShow,曾以笔记本的第二屏、智能遥控器和智能键盘的面目出现,华硕、三星的笔记本就包含这样的SideShow显示屏。
但是无论是MSN Direct,还是SideShow,其产品并不成功,这和微软早期强制推广.NET战略相关的,因为基于.NET技术开发此类产品,虽然开发比较快,但 是对硬件资源需求比较高,其.NET托管代码相比原生C++代码,速度要慢许多。所以此类产品一旦批量生产,性价比肯定比较低。最初微软也打算全部 用.NET 语言开发操作系统(比如Longhorn系统),后来事实证明这种做法是行不通的。
2009年起始微软开始调整.NET Micro Framework发展战略,首先以Apache 2.0 license的授权方式完全开源.NET Micro Framework,并基于.NET Micro Framework推出第三代产品Netduino,微软这个思路其实是仿照Arduino产品而做的,从产品命名还有实际硬件接口上,都是学习 Arduino。我个人认为这个思路是对的,至少充分发挥了.NET Micro Framework优势,小巧,开发迅速,并且采用强大的Visual Studio进行和在线调试,让所有的.NET程序员很容易进入到嵌入式领域进行相关开发,这不得不说在软硬件开发结合越来越紧密的时代, 对.NET程序员是一个福音。
而其后推出的基于.NET Micro Framework技术的.NET Gadgeteer产品更是充分发挥了.NET Micro Framework优势,在Netduino产品的基础上,更上一层楼,青出于蓝而胜于蓝,完全演化成具有微软自己特色的产品。特别是微软定义的20 种.NET Gadgeteer接口类型,应该是微软为工控领域制订OPC技术标准以来,最重要的一个接口标准。
更具特色的是硬件拖拉可视化编程。在DOS时代我们开发一个界面程序,可以说是摸着石头过河,边写代码,边运行测试,以确认相关界面的位置是否合适。 Windows平台下最初的Visual Basic等可视化编程工具,让我们的界面开发带入一个新时代,每个功能模块都被封装为一个控件,通过可视化拖拉的方式,设计界面,让我们的界面开发提升 到一个新的水平。同理,我们以软件界面开发的眼光审视目前的硬件开发,其实发现,开发模式仍处在DOS时代,每外接一个功能模块,都需要我们的程序员匠心 独运,小心翼翼分配相关的Pin脚,并用心开发相关驱动,最终通过应用程序调用底层接口,进行数据交互。
而.NET Gadgeteer的开发环境,让我们抛弃了这些琐碎和繁杂的步骤,视每个外接模块为一个控件,通过拖拉方式,让核心主板和这些模块相连,自动完成接口初 始化、模块初始化等工作。留给我们所做的,就是一些业务逻辑的实施和完善,这是硬件开发领域的面向对象编程,是一个具有里程碑意义的硬件开发变革。
有了这些特色.NET Gadgeteer已经和Netduino、Arduino等相关DIY产品不同,跳出了仅仅是学习硬件,电子产品小制作的范畴。再结合目前的发展的如火 如荼的3D打印技术,.NET Gadgeteer已经成为快速制作最终产品最好的选择(特别是小批量、个性化产品)。在物联网发展迅猛的今天,.NET Gadgeteer更是可以大显身手,可以方便接入各种传感器模块,并把相关数据上传到云端。
【说明】以上内容摘自译著《玩转.NET Gadgeteer电子积木》上的译者序,目前该书已经出版,详情可以单击下面的链接:
以前的一篇博客文章《》
(简介:)硬件简单扩展以后也可以变身成为.NET Gadgeteer主板。
1915年的时候,有个叫陈独秀的同学找来了两个哥们,德先生(民主)和赛先生(科学),颠覆了全中国
2010年前后,安先生()和艾先生(ios)联手推翻了塞班的统治,颠覆了全世界
而AR一定会成为安先生和赛先生维护统治的有力工具,今天,就带大家一起看看如何搭建AR开发环境
在这里,我们使用Qualcomm的SDK作为开发的基础,具体网址请看这里
鉴于国外有时不好上,我将主要步骤截图如下并做简单翻译
总体步骤图
前四步就不再赘述,知道AR这个单词是什么意思的肯定会做前四步
第五步相信大家也知道应该干什么,需要注意的是貌似使用这个sdk只能在2.1及以上版本开发
第六步截图如下
此步骤的主要目的是让大家安装Cywin(Cygwin是许多的集合,最初由开发,用于各种版本的上,运行系统)
(可以按照它的要求来安装,我把所有的都安上了,以防出现问题,最后要记住添加环境变量)
第七步安装android ndk只需到此下载
并在windows path 中配置环境变量(和java环境变量在一个位置)
最后可以打开cywin,切换到android ndk的任何一个例子目录下进行测试
这是在我电脑上的运行情况
接着进行QCAR SDK的安装
第一步,下载SDK
外网不好下载啊,我传到了csdn中
第二步,安装并配置环境变量
先安装第二个
这一步就有图有真相了哈
第三步,基本不用做,把手机上的usb调试打开,并安装驱动,和开发普通程序没有区别
第三大步就是激动人心的运行AR程序了
首先,第一步用Cywin编译samples程序
sdk任何例子的目录下
和这张图以一个道理的,只是转的目录要换一下
剩下的三步很简单,用eclipse打开用Cywin编译的例子,运行就哦了
嗯虽然是全是用别人的东西,但运行出来还是有点小激动的。
对此技术有兴趣的欢迎交流~
转自:http://blog.csdn.net/libaier_gc/article/details/7190736
-Vuforia SDK 环境搭建
高通公司提供关于游戏、多媒体以及效能等三方面的SDK,关于其详细的SDK相关情况的介绍,请见高通开发者专区:
点击链接进入高通开发者专区首页,接着点击“资源”即可看到我们需要下载SDK。截图如下:
点击“Vuforia SDK 针对安卓(v2.8)”进入扩增实境(Vuforia)专区。链接地址:
注意:扩增实境(Vuforia)论坛也是供我们学习交流的经验的好去处!
-Vuforia SDK 环境中文版搭建步骤如下:
1、配置 开发环境
(1)安装JDK
下载最新或者与你电脑相匹配的版本的JDK;
b.若对JDK的安装过程不熟悉,请点击:
(注意:需验证JDK是否安装成功)
(2)安装Android ADT Bundle
在这里下载 Android SDK ,该zip文件中含有Eclipse IDE /Android SDK Tools等文件;
b. 先创建一个开发Android项目的目录(如:C:\Development\Android),再将上述zip文件解压到该目录下;接着可以点击/eclipse文件夹下的eclipse.exe运行。
(3)设置SDK Manager:主要是允许你安装或更新Android平台的相关工具。步骤如下:运行Eclipse,选择 Window-&Android SDK Manager,在这里选择你需要的组件如图:(注意:其实这步可有可无,视具体情况而定)
(4) 关于Cygwin环境的设置:它是一个C++ GNU编译器,Vuforia SDK 2.8版本既包括java API也包括C++ API,一般情况下java API就能够满足Vuforia 所有的特征及应用功能。因此,一般建议使用java API,除非你一定用到C++ 本地API时,才会建议你安装cygwin。
(5)Android NDK的安装:如果你需要用到Vuforia SDK中的C++ API时,则需要安装Android NDK,否则可以跳过这一步。
安装步骤如下:首先从
下载相应版本的NDK,并将文件解压到“C:\Development\Android\”下;其次,配置环境变量(右击“我的计算机–选择参数–环境变量–再选择系统变量中的Path进行编辑–添加NDK的安装路径[;C:\Development\Android\android-ndk-rxy\]”);最后进行测试(测试,目前笔者不熟,请读者自行查找资料进行)。
2、安装Vuforia SDK
(1)下载链接:
(2)将其解压到 C:\Development\Android\下即可;
(3)设置QCAR环境变量:目的在于让SDK升级独立于应用开发,未来开发的AR项目都将位于C:\Development\Android\下;步骤如下:运行Eclipse,点击“Window–Preferences–Java–Build Path–Classpath Variables”在这里New一个变量名“QCAR_SDK_ROOT”再选择“Folder”,变量值为“C:/Development/Android/vuforia-sdk-android-xx-yy-zz”
(4)设置构建路径:目的在于你开发的Vuforia项目中有Vuforia.jar文件。右击开发项目,选择“properties– Java Build Path–Order and Export”就可以查看该项目有没有链入Vuforia.jar文件,若无,则添加进来如图所示:
3、设置测试设备(Android 智能手机)
打开手机“设置”,选择“安全”勾选“未知来源”;再就是”开发者选项”选择“USB调试”等;再就是连接电脑USB接口,检查是否能成功安装驱动。
至此,AR项目开发环境已经搭建完毕!
TreeView安装、使用(如何将TreeView打包发布)(带CheckBox选择框的TreeView的初始化,TreeView客户端操作:选择父节点后自动选择所有子节点,子节点选择后自动选择父节点)(TreeView节点精确定位)
1.下载地址
下载后是后缀为bat的版本
(1)bulid.将bulid.bat的路径指向csc.exe所在路径,生成Microsoft.Web.UI.WebControls.dll。
(2)在wwwroot下创建空目录webctrl_client\1_0。
(3)将build\Runtime下的文件拷至webctrl_client\1_0下。
(4)选择工具箱的自定义工具箱,添加Microsoft.Web.UI.WebControls.dll。
但如果你能找到后缀是msi的自动安装版本,直接下一步就行(我一直用这个版本,hoho)
安装后,通过“自定义工具箱”-&“.net框架组件”把TreeView添加到工具箱里
2.运行时无法显示
一般是TreeView的版本问题,最好下载英文版自动安装版本重新安装,安装前应该先到添加删除程序里卸掉原版本
3.显示格式出错(非树状显示)
TreeView要求客户端浏览器版本为IE5.5及以上,最好要求客户端升级为IE6.0
4.框架里使用TreeView
设置NavigateUrl、Target属性,可更新另外的Frame
5.找不到TreeNode类
使用TreeView,最好添加namespace:using Microsoft.Web.UI.WebC
6.遍历TreeView节点(递归算法)
private void Page_Load(object sender, System.EventArgs e)
GetAllNodeText(TreeView1.Nodes);
void GetAllNodeText(TreeNodeCollection tnc)
foreach(TreeNode node in tnc)
if(node.Nodes.Count!=0)
GetAllNodeText(node.Nodes);
Response.Write(node.Text + ” “);
7.得到node结点的父节点
if(node.Parent is TreeNode)
pnode=(TreeNode)node.P
//node is root node
8.修改TreeView样式(示例)
&iewc:TreeView id=”TreeView1″ runat=”server” HoverStyle=”color:background:#00ffCC;” DefaultStyle=”background:color:” SelectedStyle=”color:background:#00ff00;”&
TreeView1.DefaultStyle[“font-size”] = “20pt”;
9.展开时不提交,改变选择节点时才提交
将autopostback设置成
在body里添加
onload=”initTree()”&
然后在PageLoad里写:
strTreeName
“TreeView1″;
Page.GetPostBackEventReference(TreeView1);
“&script
language=\”\”&
“&!–
initTree()
strTreeName
“.onSelectedIndexChange
function()
(event.oldTreeNodeIndex
event.newTreeNodeIndex)
“this.queueEvent(‘onselectedindexchange’,
event.oldTreeNodeIndex
‘,’
event.newTreeNodeIndex);
“window.setTimeout(‘”
strRef.Replace(“‘”,”\\’“)
“‘,
‘’);
“&/script&”;
Page.RegisterClientScriptBlock(“InitTree”,strScript
这样就只有你点击的节点更改的时候才提交!
10.TreeView结合XML
把XML文件设置为如下格式,然后直接设置TreeNodeSrc为该XML文件就行
&?xml version=&#″ encoding=”GB;?&
&TREENODES&
&TREENODE TEXT=”node0″ EXPANDED=”true”&
&TREENODE TEXT=”node1″/&
&TREENODE TEXT=”node2″/&
&/TREENODE&
&TREENODE TEXT=”node3″ NavigateURL=”3.aspx”/&
&/TREENODES&
或者用代码
TreeView1.TreeNodeSrc=”a.xml”;
TreeView1.DataBind();
客户端控制TreeView
1.设置所选节点,如选中第二个节点
function SetSelNode()
TreeView1.selectedNodeIndex=+;
2.得到所选节点的Text,ID或NodeData
function GetAttribute()
alert(TreeView1.getTreeNode(TreeView1.selectedNodeIndex).getAttribute(“Text”));
替换Text为ID或NodeData,可分别得到所选节点的ID或NodeData
3.修改节点属性,如修改第一个节点的Text
function ModifyNode()
var node=TreeView1.getTreeNode(+);
node.setAttribute(“Text”,”hgknight”);
4.得到点击节点
function TreeView1.onclick()
alert(TreeView1.getTreeNode(TreeView1.clickedNodeIndex).getAttribute(“Text”));
5.添加节点
function AddNode()
var node=TreeView1.createTreeNode();
node.setAttribute(“Text”,”hgknight”);
TreeView1.add(node);
6.js遍历所有节点
var AllRootNode=new Array();
AllRootNode=TreeView1.getChildren();
AlertNode(AllRootNode);
function AlertNode(NodeArray)
if(parseInt(NodeArray.length)==0)
for(i=0;i&NodeArray.i++)
cNode=NodeArray[i];
alert(cNode.getAttribute(“Text”));
if(parseInt(cNode.getChildren().length)!=0)
AlertNode(cNode.getChildren());
在MVC3项目里,如果Action的参数中有Enum枚举作为对象属性的话,使用POST方法提交过来的JSON数据中的枚举值却无法正确被识别对应的枚举值。
二、Demo演示
为了说明问题,我使用MVC3项目创建Controller,并且创建如下代码演示:
//交通方式枚举
public enum TrafficEnum
public class Person
public int ID { get; set; }
public TrafficEnum Traffic { get; set; }
public class DemoController : Controller
public ActionResult Index(Person p)
return View();
生成成功之后,就可以使用来发送HTTP POST请求了,注意需要的是,要在Request Headers加上请求头content-type:application/json,这样才能通知服务器端Request Body里的内容为JSON格式。
点击右上角的Execute执行HTTP请求,在程序断点情况下,查看参数p,属性ID已经正确的被识别到了值为9999,而枚举值属性Traffic却 被错认为枚举中的首个值Bus,这俨然是错误的,纵使你将Traffic修改成Bike,也就是值等于2,结果也是一样。
三、解决方法
升级MVC4,亲测在MVC4项目下,这个问题已经被修复了;
假若因为各种原因,项目不想或者不能升级为MVC4,可以在MVC3项目上做些改动,亦可修复这个问题,
1、在项目中,新建一个类,加入以下代码,需要引用一下 ponentM
using System.Web.M 命名空间;
/// &summary&
/// 处理在MVC3下,提交的JSON枚举值在Controller不能识别的问题
/// &/summary&
public class EnumConverterModelBinder : DefaultModelBinder
protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
var propertyType = propertyDescriptor.PropertyT
if (propertyType.IsEnum)
var providerValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (null != providerValue)
var value = providerValue.RawV
if (null != value)
var valueType = value.GetType();
if (!valueType.IsEnum)
return Enum.ToObject(propertyType, value);
return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
2、在Global.asax的Application_Start方法中,进行EnumConverterModelBinder类的实例化操作:
protected void Application_Start()
//处理在MVC3下,提交的JSON枚举值在Controller不能识别的问题
ModelBinders.Binders.DefaultBinder = new EnumConverterModelBinder();
进行配置改造之后,我再次生成,重新发送HTTP请求看,MVC Action中的参数里的枚举就能被正确的识别到了。
我觉得这应该是mvc3里面一个小小的缺陷吧,随着mvc的升级,这已经在新版本里被完善修复了,可还用着mvc3的人如果在项目中遇到这个问题,可以研究一下。
遇到一个问题,去百度谷歌找解决方案是可以,但是复制粘贴完代码之后,最好问下自己,为什么这样可以解决问题。
从现象和解决代码中猜想,应该是在MVC生命周期中的Model Binders 这一环节出了问题。
因为MVC已经开源了,所以我尝试着调试源码,首先下载MVC3的源码,其他项目可以移除,只保留红色框中的项目即可,然后新建一个测试项目,并且将此测试项目的引用移除,转而引用本解决方案中的项目,这样子,我们才可以对源码进行调试操作。
搜回来的代码中可知,我们自定义的类继承DefaultModelBinder父类,并且重写了GetPropertyValue方法,那我们就从这点开始,在MVC3源码中的System.Web.MVC项目中找到该类,在此方法上插入断点。
F5调试程序,发送一个请求。
其实BindProperty方法是会被多次执行的,BindProperties方法会对请求的实体类的属性进行遍历,每一个属性都要经过BindProperty方法的处理;
现在已经截获到第一个属性ID了。
紧接着,程序进入方法。
只贴部分关键代码了,通过的获得属性的相关信息,如果不等于的话,转到执行方法。
在BindSimpleModel方法里,首先通过判断确定指定的对象是否是当前 Type 的实例,如果是,则直接返回rawValue,这里的属性类型是类型,返回
第一个Int32类型属性的部分关键代码执行到这里就已经确认到值了,接下来,我们看出了问题的枚举类型属性。
循环来到了第二个属性了,这时我留意到有个Model属性,对比类型执行的时候,这个属性当时为,而此时则为,可见这是一个默认值,指定枚举中值为的那个类型(即使你不为枚举显式指定值),同样的,经过方法来到了方法。
此时,对比Int32类型的属性ID,这次ModelType.IsInstanceOfType(valueProvideResult.RawValue)为,并且接下来不是类型就执行以下的判断,也不是数组类型,所以,来到了最后一个,根据绿色的注释可以看出,这应该是一个判断是否集合类型的方法,都不是,所以,返回了。
这时,变量为,执行最后一个
在方法里,也进行了一系列的类型判断转换,目的就是将JSON中的数字类型转换成枚举值,但是执行过程中抛出异常了,原因是
“” 也就是说,在MVC3的机制中,并没有相应的type converter来处理数值与枚举的对应。
经过以上这些处理方法,都没完成把对应的值确认下来,怎么给原来的 老大方法交差呢,所以,小的只好将和 模型错误状态信息如实带回去了,让老大决定怎么做,老大后面处理这里有点绕,但是我看源码估计也是拿默认值来充当Value了,所以就造成了JSON传过来的值与对应枚举的值不对应的情况,无论传什么值,结果都是第一个枚举的值。
这篇文章只是我在工作上遇到的一个小问题,然后有点小兴趣就从源码的角度上来研究和分析,缺乏理论的依据,因为之前没有很深入的去研究MVC的底层运行机制与生命周期,所以这方面还需要得加强学习一下,如果你也有兴趣,可以下载来分析一下,甚至可以下载MVC4的源码来进行对比。
上一篇已经搭建好整体框架,实现了入口的验证,
验证通过后就交给LookMsgType方法处理,LookMsgType方法主要是对微信发来的不同的消息进行分解,不同的类型交给业务逻辑层不同的方 法处理,
对不同类型的消息判断,可以用if,也可以用switch
一般来说超过5个的if用switch会更好, 这里贴出LookMsgType方法:
public void LookMsgType(string msgType)
#region 判断消息类型
switch (msgType)
case &text&:
RText mText = new RText();
mText = ReadXml.GetModel(mText, xmlModel);
BLLWei.DoText(dbHome, mText);//文本消息
case &image&:
RImg mImg = new RImg();
mImg = ReadXml.GetModel(mImg, xmlModel);
BLLWei.DoImg(dbHome,mImg);//图片
case &voice&: //声音
RVoice mVoice = new RVoice();
mVoice = ReadXml.GetModel(mVoice, xmlModel);
BLLWei.DoVoice(dbHome,mVoice);
case &video&://视频
RVideo mVideo = new RVideo();
mVideo = ReadXml.GetModel(mVideo, xmlModel);
BLLWei.DoVideo(dbHome, mVideo);
case &location&://地理位置
RLocation mLocation = new RLocation();
mLocation = ReadXml.GetModel(mLocation, xmlModel);
BLLWei.DoLocation(dbHome,mLocation);
case &link&://链接
RLink mLink = new RLink();
mLink = ReadXml.GetModel(mLink, xmlModel);
BLLWei.DoLink(dbHome,mLink);
#region 事件
case &event&:
switch (ReadXml.ReadModel(&Event&, xmlModel))
case &subscribe&:
if (ReadXml.ReadModel(&EventKey&, xmlModel).IndexOf(&qrscene_&) &= 0)
RCodeNotSub mNotSub = new RCodeNotSub();
mNotSub = ReadXml.GetModel(mNotSub, xmlModel);
BLLWei.DoCodeNotSub(dbHome,mNotSub);//未关注的新用户,扫描带参数的二维码关注
RSub mSub = new RSub();
mSub = ReadXml.GetModel(mSub, xmlModel);
BLLWei.DoSub(dbHome,mSub);//普通关注
case &unsubscribe&:
RUnsub mUnSub = new RUnsub ();
mUnSub = ReadXml.GetModel(mUnSub, xmlModel);
BLLWei.DoUnSub(dbHome,mUnSub);//取消关注
case &SCAN&:
RCodeSub mCodeSub = new RCodeSub();
mCodeSub = ReadXml.GetModel(mCodeSub, xmlModel);
BLLWei.DoCodeSub(dbHome,mCodeSub);//已经关注的用户扫描带参数的二维码
case &LOCATION&://用户上报地理位置
RSubLocation mSubLoc = new RSubLocation();
mSubLoc = ReadXml.GetModel(mSubLoc, xmlModel);
BLLWei.DoSubLocation(dbHome, mSubLoc);
case &CLICK&://自定义菜单点击
RMenuClick mMenuClk = new RMenuClick();
mMenuClk = ReadXml.GetModel(mMenuClk, xmlModel);
BLLWei.DoMenuClick(dbHome, mMenuClk);
case &VIEW&://自定义菜单跳转事件
RMenuView mMenuVw = new RMenuView();
mMenuVw = ReadXml.GetModel(mMenuVw, xmlModel);
BLLWei.DoMenuView(dbHome, mMenuVw);
#endregion
#endregion
外层switch判断msgtype,
在event类型时,再次switch判断具体的事件类型(关注、取消关注、自定义菜单事件等),
至此所有的微信发来的消息都有处理了,在上面代码中用到消息模型以及ReadXml.GetModel方法给模型赋值, 赋值之后传递给业务逻辑层对应的方法处理,
下面写出消息封装和给模型赋值的方法。
1、消息封装:
对所有微信发来的消息进行封装, 在datamodel中建一个Receive文件夹和一个send文件夹,在其中分别建立对应消息的类,完成之后,完整的datamodel类库如下图:
—–接收消息:
文本消息RText.cs
public class RText
public string ToUserName { }// 开发者微信号
public string FromUserName { }// 用户号(OpenID)
public long CreateTime { }// 创建时间
public string MsgType { } //消息类型
public string Content { }//内容
public long MsgId { }//消息ID
自定义菜单点击RMenuClick.cs
public class RMenuClick
public string ToUserName { }// 开发者微信号
public string FromUserName { }// 用户号(OpenID)
public long CreateTime { }// 创建时间
public string MsgType { } //消息类型
public string Event { }//事件类型
public string EventKey { }//事件key
其他也都类似,不一一列举。
—–发送消息
发送文本消息SText.cs
public class SText
public string ToUserName { }// 用户号(OpenID)
public string FromUserName { }// 开发者微信号
public long CreateTime { }// 创建时间
public string MsgType { get { return &text&; } } //消息类型
public string Content { }//内容
发送图文消息SNews.cs
namespace DataModel.Send
public class SNews
public string ToUserName { }// 用户号(OpenID)
public string FromUserName { }// 开发者微信号
public long CreateTime { }// 创建时间
public string MsgType { get { return &news&; } } //消息类型
public int ArticleCount { }//图文个数
public List&ArticlesModel& Articles { }//图文列表
public class ArticlesModel //默认第一条大图显示
public string Title { }//标题
public string Description { }//描述
public string PicUrl { }//图片链接
public string Url { }//点击之后跳转的链接
发送图文消息
在发送图文消息中,因为回复给微信的图文消息中,具体的图文内容是多条(最多可以10条),所以单独会有ArticlesModel。
后面文章会写出图文消息的发送。
2、通过反射给model赋值
在上篇文章写的入口处,已经有了解析xml的方法,现在封装了消息,通常的做法,是每次用到对应的model就手动写代码赋值,
而我这里LookMsgType方法中所有给消息赋值时全用的ReadXml.GetModel这同一个方法,
这里用的就是反射,方法如下:
/// &summary&
/// 通过反射给接收消息model赋值
/// &/summary&
/// &typeparam name=&T&&&/typeparam&
/// &param name=&model&&&/param&
/// &returns&&/returns&
public static T GetModel&T&(T model, Dictionary&string, string& xmlModel) where T : class
var m = model.GetType();
foreach (PropertyInfo p in m.GetProperties())
string name = p.N
if (xmlModel.Keys.Contains(name))
string value=xmlModel.Where(x =& x.Key == name).FirstOrDefault().V
p.SetValue(model,
string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, p.PropertyType), null);
T model 就是要使用的消息类,
xmlmodel是在入口处传递进来的解析的微信发来的xml信息,
这样,就不需要每次手动写代码赋值了。
好了,此篇实现了lookmsgtype方法, 实现了消息封装和反射赋值, 接下去就是到了业务逻辑层中的处理和具体实现了…
备案信息:

我要回帖

更多关于 跳大神是什么意思 的文章

 

随机推荐