[转载]关于QQ一些功能的实现

mikel阅读(1174)

[转载]关于QQ一些功能的实现 – Create Chen – 博客园.

在网上搜了很久关于腾讯的接口, 但资料很有限, 绝大部分都是重复的, 由于想实现一些比较好玩的应用, 我只好根

据手头能搜到的资料进行实现了. 现在可以实现QQ登陆, 发消息, 接受消息, 加好友, 查询好友资料, 更改QQ状态, 查询

已添加的好友(只能按QQ号排序, 获取到前120名名单, 原因不明), 查看某QQ用户个人资料等功能, 可以给有兴趣的同学

们参考一下. 也请有这方面经验的前辈们补充补充你们知道的其它功能:)

原理是向腾讯http://tqq.tencent.com:8000 进行POST一个UTF8编码的Byte[], 这个数组是根据各个功能的协

议进行编码的, 成功后返回一个UTF8编码的Byte[]数组, 因此我把这个方法抽取出来:

private void UploadData() { try { pageData = _client.UploadData("http://tqq.tencent.com:8000", "POST", byteArray); } catch { } }

类中定义的变量:

public string num; //构造函数的QQ号码 private string pwd; //构造函数的QQ密码 public string[] online_Face={""}; //在线的头像号码 public string[] online_Station={""}; //在线的状态 public string[] online_Number={""}; //在线的号码 public string[] online_NameK={""}; //在线的昵称 private WebClient _client = new WebClient(); //用来给服务器发送消息的 private string postValues; //发送给服务器的字符串 private byte[] byteArray; //把要发送的字符串变成字符数组 private byte[] pageData; //接受服务器返回的字符数组 private string s; //把返回的字符数组变成字符串 public string[] MT; //储存信息类型 public string[] UN; //储存信息来源号码 public string[] MG; //储存信息内容 public bool is_RightLogin; //判断当前用户是否正确登录

构造一个QQ类实例的构造函数:

/// <summary> /// QQ类的构造函数 /// </summary> /// <param name="QQ_Num">QQ号码</param> /// <param name="QQ_Pwd">QQ密码</param> public QQ (string QQ_Num, string QQ_Pwd) { this.num = QQ_Num; this.pwd = QQ_Pwd; }

实现QQ登陆的功能:

协议: VER=1.1&CMD=Login&SEQ=&UIN=&PS=&M5=1&LC=9326B87B234E7235

解释: VER是用来说明QQ协议的版本,CMD是说明协议的命令,Login就是指QQ的登录了, SEQ是他的为了防止

重复发送而设定的一个标记,可以取时间得毫秒值, 一个随机数也可以, UIN是说明你当前要登录的用户QQ号, PS是M

D5加密过后的密码的值.

/// <summary> /// 登陆QQ /// </summary> /// <returns>登陆成功就返回True</returns> public bool QQ_Login() { postValues = "VER=1.1&CMD=Login&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&PS=" + MD5(pwd) + " &M5=1&LC=9326B87B234E7235"; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); if (Encoding.UTF8.GetString(pageData).Contains("RES=0&RS=0")) { is_RightLogin = true; return true; } else return false; }

QQ的MD5加密方法:

public static string MD5(string toCryString) { MD5CryptoServiceProvider hashmd5; //using System.Security.Cryptography安全.密码系统 hashmd5 = new MD5CryptoServiceProvider(); return BitConverter.ToString(hashmd5.ComputeHash(Encoding.UTF8.GetBytes(toCryString))).Replace("-", "").ToLower(); }

QQ登陆的返回协议: VER=1.1&CMD=Login&SEQ=&UIN=&RES=0&RS=0&HI=60&LI=300(这是登陆成功的一个例子)

解释: RES为0表示成功返回,RS为0表示登录成功, VER=1.1&CMD=Login&SEQ=&UIN=&RES=0&RS=1&RA=登录失败

RS为1表示登录失败,那么就会出现提示信息RA说明原因.

获取QQ好友列表:

协议: VER=1.1&CMD=List&SEQ=&UIN=&TN=160&UN=0

/// <summary> /// 获取QQ好友列表 /// </summary> /// <returns>返回一个字符串数组,数组最后一个元素是空格</returns> public string[] QQ_List() { postValues = "VER=1.1&CMD=List&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=160&UN=0"; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (!s.Contains("&RES=0")) is_RightLogin = false; string s2 = s.Remove(0, s.IndexOf("&UN=")+4); string[] QQ_Friend_List = s.Split(','); return QQ_Friend_List; }

返回协议: VER=1.1&CMD=LIST&SEQ=&UIN=&RES=0&FN=1&SN=&UN=

解释: UN后面则是您好友的QQ号码,每个号码都由,进行分开, 我用string.Split(‘,’)把值放入字符串数组中返回了.

更新目前在线online_四个字符串数组中好友信息的值:

协议: VER=1.1&CMD=Query_Stat&SEQ=&UIN=&TN=50&UN=0

解释: 获得QQ好友在线名单跟获得好友名单差不多,不同的是用的命令不同用的是Query_Stat

/// <summary> /// 更新QQ类中目前在线online_四个字符串数组的值 /// </summary> public void QQ_Query_Stat() { postValues = "VER=1.1&CMD=Query_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&TN=50&UN=0"; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (!s.Contains("&RES=0")) is_RightLogin = false; StringBuilder sb = new StringBuilder(s); sb.Remove(s.IndexOf("&FN="), s.Length - s.IndexOf("&FN=")); sb.Remove(0,s.IndexOf("&FC=")+4); online_Face = sb.ToString().Split(','); sb = new StringBuilder(s); sb.Remove(s.IndexOf("&UN="), s.Length - s.IndexOf("&UN=")); sb.Remove(0, s.IndexOf("&ST=") + 4); online_Station = sb.ToString().Split(','); sb = new StringBuilder(s); sb.Remove(s.IndexOf("&NK="), s.Length - s.IndexOf("&NK=")); sb.Remove(0, s.IndexOf("&UN=") + 4); online_Number = sb.ToString().Split(','); string ss = s.Remove(0, s.IndexOf("&NK=") + 4); online_NameK = ss.Split(','); }

返回协议: VER=1.1&CMD=QUERY_STAT&SEQ=9118265&UIN=634882287&RES=0&FC=12,&FN=1&SN=1

&ST=10,&UN=635478153,&NK=,

解释: FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1, ST为QQ用户的状态,

10为上线,20为离线,30为忙碌, UN为在线用户的QQ号,NK为在线用户的QQ昵称.ST,UN,NK,每个逗号隔开的数据相互对应.

输入一个QQ号,查询这个QQ号用户的信息:

协议: VER=1.1&CMD=GetInfo&SEQ=&UIN=&LV=2&UN=

解释: UN为要查看用户信息的QQ号.

/// <summary> /// 输入一个QQ号,查询这个QQ号用户的信息 /// </summary> /// <param name="search_num">输入一个QQ号,查询该QQ信息</param> /// <returns>字符串数组(联系地址,用户年龄,用户邮箱,头像,个人网站,职业,邮箱,联系电话,简介,省份,真实姓名,毕业院校,性别,QQ号,昵称)</returns> public string[] QQ_GetInfo(string search_num) { postValues = "VER=1.1&CMD=GetInfo&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&LV=2&UN=" + search_num; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (!s.Contains("&RES=0")) is_RightLogin = false; MatchCollection matches = Regex.Matches(s, "&([^=][^=])=([^&]*)"); List<string> Info = new List<string>(); for (int i = 0; i < matches.Count; i++) Info.Add(matches[i].Groups[2].ToString()); Info.RemoveAt(6); //去除LV=多少, 这表示查询方式,默然就是普通查询 if (Info[12].ToString() == "0") Info[12] = ""; else Info[12] = ""; string[] Inf = Info.ToArray(); return Inf; }

返回协议: VER=1.1&CMD=GETINFO&SEQ=41707&UIN=&RES=0&AD=&AG=&EM=&FC=&HP=&JB=&LV=&PC=&PH=&

PR=PV=&RN=&SC=&SX=&UN=&NK=

解释: AD用户的联系地址, AG为用户年龄, EM为用户MAIL, FC为用户头像, HP为用户网站, JB为用户职业, PC为用户邮编, PH为用户

联系电话, PR为用户简介, PV为用户所以的省, RN为用户真实名称, SC为用户毕业院校, SX为用户性别, UN为用户QQ号, NK为用户QQ昵称

添加好友功能:

协议: VER=1.1&CMD=AddToList&SEQ=&UIN=&UN=

解释: UN为我们要增加用户的QQ号

/// <summary> /// 添加好友功能 /// </summary> /// <param name="fir_num">输入一个QQ号,请求加为好友</param> /// <returns>0表示已经加为好友,1表示需要验证请求,2表示拒绝</returns> public string AddToList(string fir_num) { postValues = "VER=1.1&CMD=AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fir_num; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (!s.Contains("&RES=0")) is_RightLogin = false; MatchCollection matchs = Regex.Matches(s,"&CD=(.)"); return matchs[0].Groups[1].ToString(); }

返回协议: VER=1.1&CMD=AddToList&SEQ=&UIN=&RES=0&CD=0&UN=

解释: CD为被加QQ的身份验证状态,CD为0表示”允许任何人把我列为好友”
CD为1表示”需要身份证认才能把我列为好友”,CD为2表示”不允许任何人把我列为好友”
如果CD为0那么信息回馈后,用户就直接加为好友了,如果CD为1,那么还要发送一次回应加为好友的响应

回应添加好友的请求:

协议: VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&UN=&CD=&RS=

解释: CD为响应状态, CD为0表示”通过验证”, CD为1表示”拒决加为对方为好友”

/// <summary> /// 回应加为好友的响应 /// </summary> /// <param name="fri_Num">请求的QQ号码</param> /// <param name="agree_Type">0表示通过验证,1表示拒绝对方,2表示请求加对方为好友</param> public void Ack_AddToList(string fri_Num,string agree_Type) { //WebClient _client = new WebClient(); postValues = "VER=1.1&CMD=Ack_AddToList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + fri_Num + "&CD="+agree_Type+"&RS="; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s=Encoding.UTF8.GetString(pageData); if (!s.Contains("&RES=0")) is_RightLogin = false; }

成功操作后返回协议: VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&RES=0&

删除好友:

协议: VER=1.1&CMD=DelFromList&SEQ=&UIN=&UN=

解释: UN为你要删除的QQ号

/// <summary> /// 删除好友,成功返回True /// </summary> /// <param name="del_num">输入一个QQ号,删除这个QQ好友</param> /// <returns></returns> public bool DelFromList(string del_num) { postValues = "VER=1.1&CMD=DelFromList&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + del_num; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (s.Contains("&RES=0")) return true; else return false; }

操作成功返回协议: VER=1.1&CMD=DelFromList&SEQ=&UIN=&RES=0&

改变QQ当前状态(在线,离线,忙碌):

协议: VER=1.1&CMD=Change_Stat&SEQ=&UIN=&ST=

解释: ST为要改变的状态,10为上线,20为离线,30为忙碌.

public bool Change_Stat(string stat) { postValues = "VER=1.1&CMD=Change_Stat&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&ST=" + stat; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if(s.Contains("&RES=0")) return true; else return false; }

成功操作后返回协议: VER=1.1&CMD=Change_Stat&SEQ=&UIN=&RES=0&

给QQ好友发送消息:

协议: VER=1.1&CMD=CLTMSG&SEQ=&UIN=&UN=&MG=

解释: UN是你的QQ好友, MG就是消息内容

/// <summary> /// 向一个QQ号码发送消息 /// </summary> /// <param name="msgTo">输入一个QQ号,向他发送消息</param> /// <param name="msg">输入消息内容</param> /// <returns>成功返回True</returns> public bool QQ_SendMsg(string msgTo, string msg) { postValues = "VER=1.2&CMD=CLTMSG&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num + "&UN=" + msgTo + "&MG=" + msg; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (s.Contains("&RES=20")) { is_RightLogin = false; return false; } if (s.Contains("&RES=0")) return true; else return false; }

返回协议: VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=0&(成功发送,对方不一定能收到哦)
VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=3(发送过快)
VER=1.1&CMD=CLTMSG&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)
解释: 1. 当你发消息时,以下情形对方可能看不到(其实是收到了,QQ不提示)你发送的消息:
你俩互为陌生人,且对方没有和你说过话
你在他的陌生人列表里,并且他没有和你说过话(没有验证)

2. 当你过快发送消息时,系统会给你一个惩罚,RES=3,相应时间20s

接收QQ消息:

协议: VER=1.1&CMD=GetMsgEx&SEQ=&UIN=

解释: 这个不需要解释了, 看懂前面的协议, 这个肯定能看懂的, 呵呵

public void GetMsgEx() { postValues = "VER=1.1&CMD=GetMsgEx&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (s.Contains("\r")) s = s.Replace("\r", "\n"); if (s.Contains("&RES=0")) { is_RightLogin = true; MatchCollection matches = Regex.Matches(s, "&MN=([^&]*)"); if (matches[0].Groups[1].ToString() != "0") //判断返回的信息数量是否为0条 { matches = Regex.Matches(s, "&MT=([^&]*)&UN=([^&]*)&MG=([^&]*)"); MT = matches[0].Groups[1].ToString().Split(','); //信息类型 UN = matches[0].Groups[2].ToString().Split(','); //信息来源号码 s = s.Remove(0, s.IndexOf("&MG=") + 4); MG = s.Split(','); //信息内容 //将消息内容进行转码 for(int i = 0; i<MG.Length-1;i++) { MG[i] = MG[i].Replace("%25", "%"); MG[i] = MG[i].Replace("%26", "&"); MG[i] = MG[i].Replace("%2c", ","); } } else { MT = null; UN = null; MG = null; is_RightLogin = false; } }

返回协议: VER=1.1&CMD=GETMSGEX&SEQ=&UIN=&RES=0&MN=&MT=,&UN=,&MG=,(正确返回的)

VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=0&MN=0&MT=&UN=&MG=(表示没有信息)

VER=1.1&CMD=GETMSGEX&SEQ=标记&UIN=QQ号&RES=20(没有正确登陆)

解释: 关于MT:
9为用户消息,99为系统消息,2为请求信息,3为通过验证,4为拒绝被加好友

当MT=2时,MG为对方请求你验证的信息
当MT=3时,表示对方通过你的验证
当MT=4时,MG为对方拒绝你理由
关于MG:
当MT=9时,MG为用户发送的消息内容
当MT=99时,
MG=10(QQ_STATUS_ONLINE)表示对方上线
MG=20(QQ_STATUS_OFFLINE)表示对方下线
MG=30(QQ_STATUS_BUSY)表示对方进入忙碌状态

退出QQ:

协议: VER=1.1&CMD=Logout&SEQ=&UIN=

解释: 这个也不解释, 非常简单

/// <summary> /// QQ退出登陆,并改变is_RightLogin为False /// </summary> public void QQ_Logout() { postValues = "VER=1.1&CMD=Logout&SEQ=" + DateTime.Now.Ticks.ToString().Substring(7, 7) + "&UIN=" + num; byteArray = System.Text.Encoding.UTF8.GetBytes(postValues); //向服务器POST数据 UploadData(); s = Encoding.UTF8.GetString(pageData); if (s.Contains("&RES=0")) is_RightLogin = false; }

成功返回协议: VER=1.1&CMD=LOGOUT&SEQ=&UIN=&RES=0

结尾

这些功能研究了两三天, 代码写的不好的地方请各位大牛们指点指点. 本篇最主要的目的还是抛砖引玉, 希望关于QQ其

它一些有意思的功能, 自己可以实现的, 欢迎各位高手前辈补充补充:)

点击下载 : 点击

下载地址: http://cid-07452800dc0167da.office.live.com/browse.aspx/.Public/Contact?uc=1

转载请注明: http://www.cnblogs.com/technology/ Create Chen

[转载]VS2010快捷键

mikel阅读(983)

[转载]VS2010快捷键 – 天行健@中国元素 – 博客园.

有人发了VS2010的快捷键,不够全,那才哪到哪呀,我来发个完整的 吧,后附VS2008的快捷键

Ctrl+E,D —-格式化全部代码

Ctrl+E,F —-格式化选中的代码

CTRL + SHIFT + B生成解决方案

CTRL + F7 生成编译

CTRL + O 打开文件

CTRL + SHIFT + O打开项目

CTRL + SHIFT + C显示类视图窗口

F4 显示属性窗口

SHIFT + F4显示项目属性窗口

CTRL + SHIFT + E显示资源视图

F12 转到定义

CTRL + F12转到声明

CTRL + ALT + J对象浏览

CTRL + ALT + F1帮助目录

CTRL + F1 动态帮助

F1 帮助

SHIFT + F1当前窗口帮助

CTRL + ALT + F3帮助-搜索

SHIFT + ALT + ENTER全屏显示

CTRL + -向后定位

CTRL + SHIFT + -向前定位

CTRL + F4关闭文档窗口

CTRL + PAGE DOWN光标定位到窗口上方

CTRL + PAGE UP光标定位到窗口下方

CTRL + F6

CTRL + TAB下一个文档窗口

CTRL + SHIFT + F6

CTRL + SHIFT + TAB上一个文档窗口

ALT + F6下一个面板窗口

CTRL + K, CTRL + L取消remark

CTRL + K, CTRL + C注释选择的代码

CTRL + K, CTRL + U取消对选择代码的注释

CTRL + M, CTRL + O折叠代码定义

CTRL + M, CTRL + L展开代码定义

CTRL + DELETE删除至词尾

CTRL + BACKSPACE删除至词头

SHIFT + TAB取消制表符

CTRL + U转小写

CTRL + SHIFT + U转大写

CTRL + SHIFT + END选择至文档末尾

CTRL + SHIFT + HOME选择至文档末尾开始

SHIFT + END选择至行尾

SHIFT + HOME选择至行开始处

SHIFT + ALT + END垂直选择到最后尾

SHIFT + ALT + HOME垂直选择到最前面

CTRL + SHIFT + PAGE UP选择至本页前面

CTRL + SHIFT + PAGE DOWN选择至本页后面

CTRL + END文档定位到最后

CTRL + HOME文档定位到最前

CTRL + A全选

CTRL + W选择当前单词

CTRL + G转到…

CTRL + K, CTRL + P上一个标签

CTRL + K, CTRL + N下一个标签

ALT + F10调试-ApplyCodeChanges

CTRL + ALT+ Break停止调试

CTRL + SHIFT + F9 取消所有断点

CTRL + F9允许中断

CTRL + SHIFT + F5调试-重新开始

F5运行调试

CTRL + F5运行不调试

F10跨过程序执行

F11单步逐句执行

CTRL + J列出成员

CTRL + PAGE DOWN下一个视图

CTRL + B格式-粗体

CTRL + SHIFT + T格式-文字缩进

调试快捷键

F6: 生成解决方案

Ctrl+F6: 生成当前项目

F7: 查看代码

Shift+F7: 查看窗体设计器

F5: 启动调试

Ctrl+F5: 开始执行(不调试)

Shift+F5: 停止调试

Ctrl+Shift+F5: 重启调试

F9: 切换断点

Ctrl+F9: 启用/停止断点

Ctrl+Shift+F9: 删除全部断点

F10: 逐过程

Ctrl+F10: 运行到光标处

F11: 逐语句

编辑快捷键

Shift+Alt+Enter: 切换全屏编辑

Ctrl+B,T / Ctrl+K,K: 切换书签开关

Ctrl+B,N / Ctrl+K,N: 移动到下一书签

Ctrl+B,P: 移动到上一书签

Ctrl+B,C: 清除全部标签

Ctrl+I: 渐进式搜索

Ctrl+Shift+I: 反向渐进式搜索

Ctrl+F: 查找

Ctrl+Shift+F: 在文件中查找

F3: 查找下一个

Shift+F3: 查找上一个

Ctrl+H: 替换

Ctrl+Shift+H: 在文件中替换

Alt+F12: 查找符号(列出所有查找结果)

Ctrl+Shift+V: 剪贴板循环

Ctrl+左右箭头键: 一次可以移动一个单词

Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。

Ctrl+Shift+L: 删除当前行

Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态

Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态

Ctrl+M,P: 停止大纲显示

Ctrl+E,S: 查看空白

Ctrl+E,W: 自动换行

Ctrl+G: 转到指定行

Shift+Alt+箭头键: 选择矩形文本

Alt+鼠标左按钮: 选择矩形文本

Ctrl+Shift+U: 全部变为大写

Ctrl+U: 全部变为小写

代码快捷键

Ctrl+J / Ctrl+K,L: 列出成员

Ctrl+Shift+空格键 / Ctrl+K,P: 参数信息

Ctrl+K,I: 快速信息

Ctrl+E,C / Ctrl+K,C: 注释选定内容

Ctrl+E,U / Ctrl+K,U: 取消选定注释内容

Ctrl+K,M: 生成方法存根

Ctrl+K,X: 插入代码段

Ctrl+K,S: 插入外侧代码

F12: 转到所调用过程或变量的定义

窗口快捷键

Ctrl+W,W: 浏览器窗口

Ctrl+W,S: 解决方案管理器

Ctrl+W,C: 类视图

Ctrl+W,E: 错误列表

Ctrl+W,O: 输出视图

Ctrl+W,P: 属性窗口

Ctrl+W,T: 任务列表

Ctrl+W,X: 工具箱

Ctrl+W,B: 书签窗口

Ctrl+W,U: 文档大纲

Ctrl+D,B: 断点窗口

Ctrl+D,I: 即时窗口

Ctrl+Tab: 活动窗体切换

Ctrl+Shift+N: 新建项目

Ctrl+Shift+O: 打开项目

Ctrl+Shift+S: 全部保存

Shift+Alt+C: 新建类

Ctrl+Shift+A: 新建项

VS2005的隐藏快捷键

这里我将会把一些无意中发现的VS2005中没有明确指出的快捷键共享出来,并不是所有的快捷键,或者常见的一些快捷键。

1、Ctrl+Space直接完成类或函数(本来这个并不算隐藏的快捷键,但是因为中文输入法抢占这个快捷键,所以。。。,替代的快捷键是Alt+Right)

2、Shift+Delete整行删除,并且将这一行放到剪贴板(这时候不能选中一段内容)

3、Shift+Insert粘贴,有点匪夷所思,Ctrl+V就可以了,大概是为了和Shift+Delete对应吧

4、Ctrl+Up,Ctrl+Down滚动编辑器,但尽量不移动光标,光标保证在可见范围内

5、Ctrl+BackSpace,Ctrl+Delete整词删除,有的时候很有用

6、Ctrl+Left,Ctrl+Right按整词移动光标(不算隐藏,和前面几条加起来就是Ctrl光标控制套件了)

7、Alt+Shift+F10打开执行改名,实现接口和抽象类的小窗口(还可以用Ctrl+.,不过有的中文输入法用到这个)

8、Shift+F9调试是打开QuickWatch,内容是当前光标所在处的内容

9、F12转跳到定义,很有用的快捷键

10、Shift+F12查找所有引用

—————————————VS2008快捷键大全—————————-

Ctrl+m+Crtr+o折叠所有大纲

Ctrl+M+Crtr+P: 停止大纲显示

Ctrl+K+Crtr+C: 注释选定内容

Ctrl+K+Crtr+U: 取消选定注释内容

Ctrl+J : 列出成员智能感知

Shift+Alt+Enter: 切换全屏编辑

Ctrl+B,T / Ctrl+K,K: 切换书签开关

Ctrl+B,N / Ctrl+K,N: 移动到下一书签

Ctrl+B,P: 移动到上一书签

Ctrl+B,C: 清除全部标签

Ctrl+I: 渐进式搜索

Ctrl+Shift+I: 反向渐进式搜索

Ctrl+F: 查找

Ctrl+Shift+F: 在文件中查找

F3: 查找下一个

Shift+F3: 查找上一个

Ctrl+H: 替换

Ctrl+Shift+H: 在文件中替换

Alt+F12: 查找符号(列出所有查找结果)

Ctrl+Shift+V: 剪贴板循环

Ctrl+左右箭头键: 一次可以移动一个单词

Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。

Ctrl+Shift+L: 删除当前行

Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态

Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态

Ctrl+E,S: 查看空白

Ctrl+E,W: 自动换行

Ctrl+G: 转到指定行

Shift+Alt+箭头键: 选择矩形文本

Alt+鼠标左按钮: 选择矩形文本

Ctrl+Shift+U: 全部变为大写

Ctrl+U: 全部变为小写

代码快捷键

Ctrl+Shift+空格键 / Ctrl+K,P: 参数信息

Ctrl+K,I: 快速信息

Ctrl+E,U / Ctrl+K,U: 取消选定注释内容

Ctrl+K,M: 生成方法存根

Ctrl+K,X: 插入代码段

Ctrl+K,S: 插入外侧代码

F12: 转到所调用过程或变量的定义

窗口快捷键

Ctrl+W,W: 浏览器窗口

Ctrl+W,S: 解决方案管理器

Ctrl+W,C: 类视图

Ctrl+W,E: 错误列表

Ctrl+W,O: 输出视图

trl+W,P: 属性窗口

Ctrl+W,T: 任务列表

Ctrl+W,X: 工具箱

Ctrl+W,B: 书签窗口

Ctrl+W,U: 文档大纲

Ctrl+D,B: 断点窗口

Ctrl+D,I: 即时窗口

Ctrl+Tab: 活动窗体切换

Ctrl+Shift+N: 新建项目

Ctrl+Shift+O: 打开项目

Ctrl+Shift+S: 全部保存

Shift+Alt+C: 新建类

Ctrl+Shift+A: 新建项

Shift+Alt+Enter: 切换全屏编辑

Ctrl+B,T / Ctrl+K,K: 切换书签开关

Ctrl+B,N / Ctrl+K,N: 移动到下一书签

Ctrl+B,P: 移动到上一书签

Ctrl+B,C: 清除全部标签

Ctrl+I: 渐进式搜索

Ctrl+Shift+I: 反向渐进式搜索

Ctrl+F: 查找

Ctrl+Shift+F: 在文件中查找

F3: 查找下一个

Shift+F3: 查找上一个

Ctrl+H: 替换

Ctrl+Shift+H: 在文件中替换

Alt+F12: 查找符号(列出所有查找结果)

Ctrl+Shift+V: 剪贴板循环

Ctrl+左右箭头键: 一次可以移动一个单词

Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。

Ctrl+Shift+L: 删除当前行

Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态

Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态

Ctrl+M,P: 停止大纲显示

Ctrl+E,S: 查看空白

Ctrl+E,W: 自动换行

Ctrl+G: 转到指定行

Shift+Alt+箭头键: 选择矩形文本

Alt+鼠标左按钮: 选择矩形文本

Ctrl+Shift+U: 全部变为大写

Ctrl+U: 全部变为小写

[转载]Jumony入门(三)初探解析器

mikel阅读(1323)

[转载]Jumony入门(三)初探解析器 – Ivony… – 博客园.

首先介绍一下Jumony是什么,Jumony是一个.NET的开源项目,项目主页位于:http://jumony.codeplex.com/,采用LGPL协议发布。

Jumony 试图提供在传统Web开发模型中许多难以解决问题的解决方案。一言蔽之,Jumony的一切基础建立在服务器端的HTML DOM之上。在服务器端将HTML(文件或动态网页技术的输出)按照客户端浏览器的处理方式解析为HTML DOM。操纵和处理HTML DOM,就像我们在客户端用JavaScript干的那些事情一样,不同的是,Jumony可以使你依托强大的.NET Framework,来解决以前用脚本和服务器端技术都难以解决的事情。

系列目录:

Jumony入门(一)从这里开始

Jumony入门(二)初识选择器

这是系列文章的第三篇,这个系列尝试一步步从一些最简单的例子开始了解怎么玩转Jumony。建议先从第一篇开始学习搭建Jumony环境,在本文的开始的时候,假设大家已经搭建好了Jumony的运行环境。

这一次我要谈到Jumony的HTML解析器,显然我自己写的简单的符合规范的HTML并不能说明解析器的功能。所以这一次我直接从互联网上随便抓一个页面来完成示范。

首先在项目中添加一个aspx文件,然后在上面放一个DataGrid来展示我们一会儿要抓取的成果,像是这样:

imageimage

那 么接下来,我们到Code Behind里面来添加一些代码,首先是要下载一个互联网的页面,我用新浪的首页来做示范,事实上你也可以换成任何你喜欢网站(例如博客园),下载网页最 简单的方式当然是WebClient,不过记得添加using System.Net哦,同时我也把Jumony的一些引用都添加上了,像这样:

image

然后创建JumonyParser的实例,并调用其Parse方法将html分析成一个IHtmlDocument:

image

Jumony Milestone 1除了提供Jumony Parser分析HTML文档之外,还可以把HtmlAgilityPack分析的文档转换成Jumony的标准DOM模型。这使得 HtmlAgilityPack也可以当作Jumony的一个Parser来使用,下面的代码展示了这一点:

image

不过,这么做之前要确保你引用了Ivony.Web.Html.HtmlAgilityPackAdaptor命名空间,AsDocument扩展方法便是在其中定义的。

HtmlAgilityPackAdaptor 为HtmlAgilityPack的DOM对象提供了一个适配器,使得其可以满足Jumony标准DOM的要求,从而使用Jumony的方法来操作。理论 上所有的HTML DOM和Parser都可以通过适配项目与Jumony适配。

这两种HTML Parser各有优劣,大家可以任选一种来完成这一次的例子。在这里我使用Jumony Parser来继续下面的例子。

分 析了新浪的首页后,接下来就要干坏事了,首先把新浪首页上所有的链接全部取出来。由于链接都是<a>定义的,所以简单的用Find( “a” )就可以选择出来。但<a>除了可以定义链接,还可以定义锚点,我们并不需要取出页面上的锚点。所以我们用”a[href]”,即包含 href属性的a标签:

image

然 后我们分析这些链接,将其目标URL取出来(即href属性),由于href可能是一个相对链接,所以我们用页面的地址 “http://www.sina.com.cn/” 作为基地址,重新计算出绝对的URL,然后我用LINQ表达式来对所有URL完成这样的操作,再放在一个匿名对象中:

image

可以看得出来,这些工作在服务器端完成的时候,是多么的简洁流畅,一气呵成。如果在客户端来完成这种事情,没有强大的.NET Framework作为后盾,一个简单的URL计算就可以难倒无数英雄好汉。

然后再为匿名对象添加一些其他有趣的属性,对链接排序,最后绑定到DataGrid上,最终的代码像这样:

image

由于DataGrid有自动生成列的特性,所以我们并不需要做些什么,它会自动的弄一个表格来展现这些数据,效果像是这样:

imageimage

把抓取的网页换成博客园首页:

image

写在最后

Jumony的确可以用来干各种各样的坏事,譬如说抓取页面,分析数据,或是新闻小偷什么的。从这一点来说,你可以说Jumony是邪恶的,但软件本来就是邪恶的,Jumony将一些很复杂的事情,提供了简单的解决方案,也许,这降低了干坏事的成本,但更多的时候,Jumony带来了生产力的飞跃。借助Jumony,我们能做的好玩的事情,要比这些邪恶的事情多多了不是么?

谢谢大家。

[转载]房产信息类网站DEDE与51地图结合的办法!

mikel阅读(996)

我所举例不需要修改任何原文件! 在原5.5基础上直接设置即可!
目标:以地图方式显示房产所处位置和信息,并以地图坐标方式控制显示信息!

设置办法:
1建立房产模型
2并建立自定义字段 “h_x”和”h_y” 这两个字段为 坐标传递数值使用!
3但是由于表单页是生成字段为了美观和操作性对两个坐标字段进行设置,经过多次试验在字段修改页“模型字段配置(文本模式) 中”对
<field:h_y itemname=”y” autofield=”1″ notsend=”0″ type=”int” isnull=”true” islist=”0″ default=”” maxlength=”250″ page=””>
</field:h_y>
<field:h_x itemname=”x” autofield=”1″ notsend=”0″ type=”int” isnull=”true” islist=”0″ default=”” maxlength=”250″ page=””>
</field:h_x>

修改成

<field:h_y itemname=”y” autofield=”1″ notsend=”0″ type=”int” isnull=”true” islist=”0″ default=”” maxlength=”250″ page=””>
<table width=”100%” border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td width=”35%” bgcolor=”#FFFFFF”></font>将您的房屋在地图中标示出来以便浏览。<br>
请完成标注后再进行下面信息的填写。 </td>
<td width=”17%” bgcolor=”#FFFFFF”><div id=”info”><span style=”cursor:pointer;” onClick=”window.open(‘/images/zuobiao.html’,’aa’,’height=500, width=700, top=200, left=100, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no’);”><img src=”/images/bz.gif” width=”147″ height=”38″></span></div></td>
<td width=”48%” bgcolor=”#FFFFFF”> <input name=”h_x” type=”text” class=”yinshang” value=”” size=”1″><span class=”4a” style=”cursor:pointer;” onClick=”window.open(‘/images/zuobiao.html’,’aa’,’height=500, width=700, top=200, left=100, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no’);”><img src=”/images/bzyes1.gif”></span></tr>
</table>
</field:h_y>
<field:h_x itemname=”x” autofield=”1″ notsend=”0″ type=”int” isnull=”true” islist=”0″ default=”” maxlength=”250″ page=””>
<table width=”100%” border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td width=”35%” bgcolor=”#FFFFFF”> </td>
<td width=”17%” bgcolor=”#FFFFFF”> </td>
<td width=”48%” bgcolor=”#FFFFFF”><input name=”h_y” type=”text” class=”yinshang” value=”” size=”1″></tr>
</table></field:h_x>

这样就可以传递坐标了!
期中使用的文件zuobiao.html 和两张图片我直接打包提供下载!
在zuobiao.html 中注意 字段的位置 对于聪明的人会明白期中的意义的!

4下面就是内容页了!
icon1.setImageUrl(“/images/1.png”);
icon1.setWidth(38);
icon1.setHeight(24);
icon后面的1是我手动填进去的 你可以将1替换成标签来 控制 出租还是出售或楼盘对应的 坐标图片!
内容页很重!
这一步修改好了以后对于首页繁多的地图信息控制就非常了解了~我也就不用举例说明首页怎么修改了!

由于是在本机做的而且没有美工所以没有浏览地址,等美化完成后打包放出!不过以上的例子和文件已经够用了!
如果想看地址实际我是以前修改的,NET版的CMS 将文件直接转嫁给了DEDE,在表单页痛疼了短时间 但是解决了!
看原地址 http://www.aiximi.cn 效果是完全一样,单DEDE多了可以控制信息数量和控制区域的设置因为DEDE更方便!

7_205714_66c4555feceecf9.gif

7_205714_82ac4d613cdf8c0.gif

7_205714_aa8c3835ff3fce0.gif

7_205714_d925ab0cc492037.gif

zb.rar (35.98 KB, 下载次数: 82)

[转载]oData另一种不用写代码就在网上提供数据服务的方法

mikel阅读(904)

[转载]oData – 另一种不用写代码就在网上提供数据服务的方法 – Footprints on the sands of time – 博客园.

先看两个例子:

这里还有更多提供/支持这种服务的链接:http://www.odata.org/blog/2010/10/28/new-odata-producers-and-consumers

这是什么?

开放数据协议(oData)让你重新认识 HTTP 协议并且简化数据在网上的发布和更新过程。参看在 cnblogs 查到的唯一介绍它的新闻:http://news.cnblogs.com/n/69756/ 和一篇写在 VS 2010 RC 时候的简介:http://www.cnblogs.com/shanyou/archive/2010/02/11/1667381.html

说正题: 用 VS 2010 + .NET V4,几乎可以不用写代码就把完整的数据服务发布到网上步骤如下:

假设你已经有一个数据库,用户可以发围脖和订阅别人的围脖,数据结构如下,

要把它变成一个网络数据服务:

1、在VS 2010 建一个Web应用或网站,加一个数据模型:

2、把数据库里的表加进来:

把默认生成的关联属性名字改改,改好就像右边这样:

3、加一个新的 WCF Data Service 网页:

4、打开它的 CS 文件,

代码

1 public class messages : DataService< /* TODO: put your data source class name here */ >
2 {
3 // This method is called only once to initialize service-wide policies.
4 public static void InitializeService(DataServiceConfiguration config)
5 {
6 // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
7 // Examples:
8 // config.SetEntitySetAccessRule(“MyEntityset”, EntitySetRights.AllRead);
9 // config.SetServiceOperationAccessRule(“MyServiceOperation”, ServiceOperationRights.All);
10 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
11 }
12 }

改成下面这个样子(基本上就是把注释去掉,把刚才的数据模型加进来):

代码

1 public class messages : DataService<MessageEntities>
2 {
3 public static void InitializeService(DataServiceConfiguration config)
4 {
5 config.SetEntitySetAccessRule(*, EntitySetRights.AllRead);
6 config.SetServiceOperationAccessRule(*, ServiceOperationRights.All);
7 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
8 }
9 }

5、没了,你的数据服务已经在网上。

浏览你的SVC网页,可以看到:

代码

1 <?xml version=”1.0″ encoding=”utf-8″ standalone=”yes” ?>
2 <service xml:base=”http://localhost:38791/messages.svc/” xmlns:atom=”http://www.w3.org/2005/Atom” xmlns:app=”http://www.w3.org/2007/app” xmlns=”http://www.w3.org/2007/app”>
3 <workspace>
4 <atom:title>Default</atom:title>
5 <collection href=”Posts”>
6 <atom:title>Posts</atom:title>
7 </collection>
8 <collection href=”Subscriptions”>
9 <atom:title>Subscriptions</atom:title>
10 </collection>
11 <collection href=”Users”>
12 <atom:title>Users</atom:title>
13 </collection>
14 </workspace>
15 </service>
16

浏览service.svc/Users,可以看到用户列表:

代码

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes” ?>

<feed xml:base=”http://localhost:38791/messages.svc/” xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices” xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” xmlns=”http://www.w3.org/2005/Atom”>
<title type=”text”>Users</title>
<id>http://localhost:38791/messages.svc/Users</id>
<updated>2010-12-20T19:22:12Z</updated>
<link rel=”self” title=”Users” href=”Users” />
<entry>
<id>http://localhost:38791/messages.svc/Users(1)</id>
<title type=”text” />
<updated>2010-12-20T19:22:12Z</updated>
<author>
<name />
</author>
<link rel=”edit” title=”User” href=”Users(1)” />
<link rel=”http://schemas.microsoft.com/ado/2007/08/dataservices/related/Posts” type=”application/atom+xml;type=feed” title=”Posts” href=”Users(1)/Posts” />
<link rel=”http://schemas.microsoft.com/ado/2007/08/dataservices/related/Followers” type=”application/atom+xml;type=feed” title=”Followers” href=”Users(1)/Followers” />
<link rel=”http://schemas.microsoft.com/ado/2007/08/dataservices/related/Subscriptions” type=”application/atom+xml;type=feed” title=”Subscriptions” href=”Users(1)/Subscriptions” />
<category term=”Message.DataModel.User” scheme=”http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
<content type=”application/xml”>
<m:properties>
<d:id m:type=”Edm.Int32″>1</d:id>
<d:name>Test</d:name>
</m:properties>
</content>
</entry>
</feed>

总结

为什么叫开放数据协议?因为它跨语言和平台的,基于http地址的数据服务。

例子:

列出所有的用户:service.svc/Users

找一个叫张三的用户:service.svc/Users?$filter=Name eq ‘张三’

他发的围脖(假设前一个查询返回了他的ID):service.svc/Users(1)/Posts

他的Fans: service.svc/Users(1)/Followers

他发的关于cnblogs的围脖:service.svc/Posts?$filter=userId eq 1 and indexof(content, ‘cnblogs’) ge 0

这些看起来并不难,但好处是,它们都不需要写任何代码,而且它是RESTful的,任何可以访问URL的语言,平台都可以用它。除此以外,这只是GET操作,POST,DELETE等其他标准HTTP操作也是原生支持的。所以,它是完整的数据服务,并不仅仅是数据查询。

如果大家有兴趣,我会继续写这个主题,比如在WPF使用这种服务,在JavaScript使用(Built in JSON support, 哈哈),并涉及一些更深的,实际项目的内容,比如数据安全,数据事务。

题外话, 为什么是另一个?很久很久以前,SQL Server曾经有过Web Service 的服务,但M$做了一个艰难的决定,把它在后续版本中移除了。由于 Entity Framework, WCF data service in .NET V4的加持,这种服务又换了一个方式回来了。

题外外话,斗转星移,离上一篇文章又两年过去了,地方没变,人老了。

人老记性就不好,这个给忘了:要修给IE的一个设置,让它不自动 turn on feed view,不然你看到就是IE格式化过的内容了,odata返回的是,人也可以吃,IE也可以吃的 Atom xml.

[转载]Jumony入门(二)初识选择器

mikel阅读(1257)

[转载]Jumony入门(二)初识选择器 – Ivony… – 博客园.

首先介绍一下Jumony是什么,Jumony是一个.NET的开源项目,项目主页位于:http://jumony.codeplex.com/,采用LGPL协议发布。

Jumony 试图提供在传统Web开发模型中许多难以解决问题的解决方案。一言蔽之,Jumony的一切基础建立在服务器端的HTML DOM之上。在服务器端将HTML(文件或动态网页技术的输出)按照客户端浏览器的处理方式解析为HTML DOM。操纵和处理HTML DOM,就像我们在客户端用JavaScript干的那些事情一样,不同的是,Jumony可以使你依托强大的.NET Framework,来解决以前用脚本和服务器端技术都难以解决的事情。

系列目录:

Jumony入门(一)从这里开始

这是系列文章的第二篇,这个系列尝试一步步从一些最简单的例子开始了解怎么玩转Jumony。建议先从第一篇开始学习搭建Jumony环境,在本文的开始的时候,假设大家已经搭建好了Jumony的运行环境。

首先我们来看一个页面:

image

这个页面的源代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Ranks</title>
  <style>
    table
    {
      font-size: 12px;
    }
    .ranks th
    {
      height: 30px;
      font-size: 15px;
      font-family: Arial;
    }
    
    .ranks td, .ranks th
    {
      border-top: solid 1px;
    }
    
    .ranks .name
    {
      font-weight: bold;
    }

    .ranks table td
    {
      border: 0px;
    }
  </style>
</head>
<body>
  <table cellpadding="5" cellspacing="0" class="ranks">
    <tr>
      <td colspan="2" class="top">
        <table cellpadding="3" border="0">
          <tr>
            <td rowspan="3"><img src="http://pic.cnblogs.com/avatar/a14218.jpg" width="50" height="50" /></td>
            <td class="name">Jumony</td>
          </tr>
          <tr>
            <td>得票数: <span style="color: red;">100</span></td>
          </tr>
          <tr>
            <td>主页地址: <a href="http://jumony.codeplex.com/">http://jumony.codeplex.com/</a></td>
          </tr>
        </table>
      </td>
    </tr>
    <tr>
      <th>
        № 2
      </th>
      <td><span class="name">Jumony</span>( <span style="color: red;">100</span> ) <a href="http://jumony.codeplex.com/">http://jumony.codeplex.com/</a></td>
    </tr>
    <tr>
      <th>
        № 3
      </th>
      <td><span class="name">Jumony</span>( <span style="color: red;">100</span> ) <a href="http://jumony.codeplex.com/">http://jumony.codeplex.com/</a></td>
    </tr>
  </table>
</body>
</html>

请先将份源代码保存为一个叫做ranks.htm的文件,然后我们开始对这个页面干点儿坏事。

这种页面,就是一种在传统的技术下,怎么也不好处理的页面,第一名的呈现方式与后面的呈现方式完全不同。即使用模版引擎,这种模版改起来怕也是件烦心事儿。

但强大CSS的选择器可以完全的抹平这些区别,使得我们的逻辑变得非常简单。

当然,首先,我们要建立一个这个页面的处理程序,也就是ranks.htm.ashx文件。然后添加using和继承基类,完成后的样子像这样:

imageimage

那么首先,我们要选择到class为ranks的那个table,再选择其每一行,选择器像是这样的:”.ranks > tr”。

中间的>符号表示只选择.ranks的直接子集中的tr,因为在第一名的行中,HTML里面又被嵌了一个table来做绑定,里面也有一些tr元素。所以我们使用>选择符来避免选择到这些:

image

关于选择器的语法,是完全遵循CSS Selector 3的标准的(部分实现)。如有不清楚的地方可以移步W3C的网站http://www.w3.org/TR/2009/PR-css3-selectors-20091215/

另外需要注意的是这里我们是直接用Find方法的,而不是Document.Find,嗯,这是JumonyHandler提供的一个便利,对于 Document的Find操作实在是太常用了,所以,Handler上定义了一个Find方法来对Document进行查找。当然,这和 Document.Find是完全一样的效果。

然后我们编造一些数据,例如:

image

接下来是将两个列表绑定在一起,Ivony.Fluent里面提供了一个方法:BindTo,这个方法可以方便的进行两个列表的绑定,使用方法像是这样:

image

这里我使用的是lambda表达式,如果你喜欢也可以写成一个额外的方法,当然,在这个例子中,由于上面的数据类型我用的是匿名类型,所以这里没有办法拆出另一个方法出来,那么,我继续用lambda来示范。

获取了每一个绑定的元素后,我们需要进一步考察每一个项(即Name、Votes和Url)要绑定的位置。只要是有规律的界面,那么其HTML就一定是有规律的,其实这个规律并不难找:

Name位于class=”name”的元素中,而Votes则总是在一个style=”color: red”的span里面,至于url,则总是在<a>那里,因为这是一个链接。当然,这个页面也可以说是事先设计好的,因为这里才第二篇,我 们只考虑一些简单的示范,在后面,我们再来看在代码中的筛选逻辑能够做到怎样的智能。那么我们可以简单的写出选择器:

image

注意这里的element直接就有Find方法,事实上Find方法并不是Document的专利,在Jumony中,只要是一个容器(IHtmlContainer),就可以Find,这实在非常便利。

OK,现在数据就已经全部绑定到页面了,打开页面来看看效果。

image

很完美不是么?看看HTML源代码:

image

怎么样,有没有一种在服务器端用JQuery的感觉?

这里有几个问题需要注意一下:

  1. CSS选择器的关系选择符,如”>”或是”+”这些,在标准中两边是不必留有空白的,即可以写成”.ranks>tr”。但Jumony不允许,是刻意如此,并非技术所限不能支持。因为Jumony认为强制性的留白可以提高这些选择符的可读性。
  2. 现有的版本中,不支持CSS Selector 3标准中的:not伪类和,选择符,其余的全部支持。JQuery的私有伪类则全部不支持。
  3. 如果你觉得linkContainer.SetAttribute( “href” ).Value( dataItem.Url )这种写法很恶心,那么不必担心。下个版本就可以这样写了:
    linkContainer.SetAttribute( “href” ,dataItem.Url )
    还可以这样:linkContainer.href = dataItem.Url

[转载]Asp.net mvc 集成Autofac和FluentValidation

mikel阅读(1178)

[转载]Asp.net mvc 集成Autofac和FluentValidation – 爱因斯坦的小脑 – 博客园.

PS:关于更多DevText的文章请到这里查看:

http://www.n-pei.com/blog/devtext_widget_Create

http://www.n-pei.com/blog/devtextdesign3

http://www.n-pei.com/blog/tools-introduce

等等。。。。。。

昨天大家很多人抱怨没有用过AutoFac,所以今天我就在把CR部署上线后,给大家说明下如何在ASP.NET mvc中集成Autofac这个IoC工具。并顺带着说明下在DevText中使用的FluentValidation。。。。

1.创建一个ASP.NET Mvc应用程序:

image

2.添加autofac引用

如果你安装了NuGet,这里你就不需要从autofac官网下载生成的dll包,而直接用vs2010自动获取。

image

这里说明下如何使用NuGet来自动添加autofac的引用。

image

再次罗嗦下,呵呵,list-package是列出所有nuget已经打包好的package。你可以在上图中看到autofac.

接下来是使用install-package来自动添加引用。

因为我们使用的是NuGet自动添加dll所以原来需要手动配置Web.Config。在httpModule中添加如下配置:

image

3.配置Gobal.asax文件

首先需要需要让这个类继承IContainerProviderAccessor接口,并声明一个IContainerProver作为应用程序的容器。

image

第二步是在Application_Start方法中注册Controller和一些model,以及modelBinder等,并使用Autofac中的自定义ControllerFactory。

image

以上就完成了Autofac的ASP.NET mvc集成。

接下来结合Autofac以及FluentValidation来给大家说明下FluentValidation如何工作。

我们使用接口IPerson和类Person来说明。

image

在Global.asax中register Person。

image

Validation部分:

先添加引用:

image

Validation的代码风格:

image

最后是Controller部分和VIew部分:

image

在Controller中注意,因为我们使用的是Autofac的ControllerFactory,所以默认Controller的Construcotr是可以有n个参数的,而不是不允许有参数。

View部分代码:

image

最后是别忘了在Global.asax中注册我们的Validation Provider。

image

搞定,直接按F5运行试试:

image

BRs

Nic

[转载]使用ASP.NET MVC MvcHandler设计自定义系统权限

mikel阅读(1016)

[转载]使用MvcHandler设计自定义系统权限 – RyanDing – 博客园.

周末稍微研究了下MVC2.0的系统框架。现将学习成果拿来和网友们分享,对MVC2.0框架研究的还不够深入。如果存在不足的地方,希望您指出,以达到共同学习的目的。

我对MVC2.0的框架的理解简单概括如下:

一、MVC2.0使用ASP.NET System.Web.Routing


画了张示意图,有点简陋:

mvc 的核心在RouteBase 这个抽象类上,该抽象类提供了两个抽象方法GetRouteData和GetVirtualPath,前者根据RouteData负责解析url后者负责生成url。


二、System.Web.Routing 的 IRouteHandler 接口


系统是如何使用IRouteHandler进入MVC框架的呢?

我的理解:MvcRouteHandler -> 通过当前的RequestContext对象生成MvcHandler对象 -> MvcHandler对象 从 RouteData 中找到 controller 通过ControllerFactory实例化MVC Controller。

MSDN上的解释:MvcRouteHandler . 此类实现了 IRouteHandler,因此可以与 ASP.NET 路由集成。 MvcRouteHandler 类将路由与 MvcHandler 实例关联。 当您使用 MapRoute 方法时,向路由注册 MvcRouteHandler 实例。 当 MvcRouteHandler 类被调用时,该类使用当前的 RequestContext 实例产生 MvcHandler 实例。 然后它会将控制委托给新 MvcHandler 实例。详情请见MSDN的MvcRouteHandler


三、加强对IRouteHandler、 MvcRouteHandler理解


为加强对MVC框架的理解,个人认为还得通过代码实践,光靠理论知识远远不够。为了加强理解以上两个对象按以下步骤模拟即可:

1.自定义HelloWorldHandler类(模拟MvcRouteHandler对象)该类实现IRouteHandler接口,代码如下:

1 public class HelloWorldHandler : IRouteHandler
2 {
3 public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
4 {
5 return new MyHandler(requestContext);
6 }
7 }

2.以上代码中的MyHandler类它模拟了MvcHandler 类,MvcHandler在RouteData中根据controller的名字创建了controller实例。MyHandler代码如下:

01 public class MyHandler : MvcHandler
02 {
03 public MyHandler(RequestContext requestContext)
04 : base(requestContext)
05 {
06
07 }
08
09 protected override System.IAsyncResult BeginProcessRequest(System.Web.HttpContext httpContext, System.AsyncCallback callback, object state)
10 {
11 if (1 == 1)
12 {
13 //当条件满足时可以跳转到一个自定义的httphandler,比如(Error.aspx)等。
14 httpContext.Response.Redirect("http://www.cnblogs.com/ryanding");
15 return null;
16 }
17 return base.BeginProcessRequest(httpContext, callback, state);
18 }
19 }

以上代码第12行这个if分支通过相应的逻辑判断,决定了是否进入MVC框架。下一篇文章中,我们就从该处着手,将权限功能注入到MyHandler的BeginProcessRequest方法内。

3.HelloWorldHandler 这个IRouteHandler调用方法如下:

在Global.asax内Application_Start改造成一下代码:

1 protected void Application_Start()
2 {
3 AreaRegistration.RegisterAllAreas();
4
5 RouteTable.Routes.Add(new Route("{controller}/{action}", new HelloWorldHandler()));
6
7 RegisterRoutes(RouteTable.Routes);
8 }


四、最后


经过以上设置,运行MVC程序后,所有的链接都将跳转到本文的3.2第14行硬编码的url。

[转载]陈成的iDebug v1.0 发布

mikel阅读(1184)

[转载]陈成的博客 » iDebug v1.0 发布.

iDebug 就像是一个魔术桶,把页面倒进去,可以出来任意你想要的东西。

Github:https://github.com/kissyteam/kissy-tools/tree/master/idebug

T181VUXeBrXXXXXXXX-876-566.png

他包含以下功能:

  • 抓网页:
    通过点击 Bookmarklet 把网页抓过来,或修改,或存档
  • responder:
    模拟 Fiddler 的 Responder 功能,对 HTML 内容进行替换
  • 查看所有 CSS 和 JS:
    模拟 YSlow 里包含的一个功能,对于不常开 Firefox 的 Chrome 用户来说非常有用
  • JS Beautify:
    格式化压缩后的脚本文件(不支持 Packer 解压缩),格式化 JSON
  • HTML Beautify:
    格式化HTML
  • Demo 模式:
    切换到 Demo 模式,保存后可在本页刷新 Demo

以下为淘宝特色功能:

  • 还原 Combo:
    把 http://a.tbcdn.cn/??a.js,b.js 替换成 http://a.tbcdn.cn/a.js 和 http://a.tbcdn.cn/b.js
  • 删除 assets 路径上的 -min
    把 http://a.tbcdn.cn/a-min.css 替换成 http://a.tbcdn.cn/a.css
  • 切换 Hosts
    不用修改 Hosts 文件,直接切换 Taobao 环境的日常/预发/线上等环境

使用方法:

  1. 确认配有 PHP 环境,并支持 SQLite
  2. 上 github 把 iDebug clone 或 下载下来
  3. 修改 iDebug.SQLite.sample 为 idebug.SQLite
  4. 访问  idebug/idebug.php
  5. 根据引导,添加页头的 bookmarklet 到收藏夹
  6. — 准备完毕 —
  7. 访问要抓取/测试的页面
  8. 点击刚才添加的 bookmarklet
  9. — 剩下的大家应该都会了 —

快捷键:

Shift + A:查看所有 CSS 和 JS
Shift + V:查看 Demo
Shift + ?:查看帮助
Shift + H:切换 Demo Mode
Ctrl + Enter:保存

规则示例:

a.css
----
b.css
====
c.js
----
d.js
e.js

说明PPT:

见 docs/idebug_20101030.pdf