<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_dudu</title><subtitle type="text">为程序员打杂的站长</subtitle><id>http://feed.cnblogs.com/blog/u/0/rss</id><updated>2012-05-17T04:18:25Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/0/rss"/><entry><id>http://www.cnblogs.com/dudu/archive/2012/05/16/mvc_renderaction_lamda_2.html</id><title type="text">续篇：新型Lamda版Html.RenderAction</title><summary type="text">我们遇到了一个问题，在RenderAction的时候需要向Action传递参数，之前实现的简陋的Html.RenderAction并没有对此提供支持，需要改进一下。向Action传参数，需要通过RouteValueDictionary，我们所要做的工作就是从Lamda表达式中获取参数名称与参数值，并还添加至RouteValueDictionary。</summary><published>2012-05-16T00:58:00Z</published><updated>2012-05-16T00:58:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/05/16/mvc_renderaction_lamda_2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/05/16/mvc_renderaction_lamda_2.html"/><content type="html">&lt;p&gt;在前一篇&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html" target="_blank"&gt;博文&lt;/a&gt;中，我们实现了一个简单的支持Lamda表达式的Html.RenderAction。&lt;/p&gt;&lt;p&gt;在评论中，&lt;a id="ctl00_CommentList_NameLink_7" href="http://home.cnblogs.com/u/33454/" rel="nofllow" target="_blank"&gt;向晚&lt;/a&gt;提到了Html.RenderAction的一个优点：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span&gt;ChildAciton的优势是可以应用OutputCahce特性实现局部缓存。&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;我们当时用Html.RenderAction，而不用Html.RenderPartial，这也是一个重要原因。&lt;/p&gt;&lt;p&gt;总结一下ChildAciton+PartialView的优势：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;可以在&amp;ldquo;不同Action相同View&amp;rdquo;中方便地被共享&lt;/li&gt;&lt;li&gt;可以在&amp;ldquo;不同Action不同View&amp;rdquo;中方便地被共享&lt;/li&gt;&lt;li&gt;&amp;ldquo;可以应用OutputCahce特性实现局部缓存&amp;rdquo;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;我们在解决另外一个问题时，发现它还有一个优势：&lt;/p&gt;&lt;p&gt;4. 可以用ChildAciton直接处理Ajax请求。&lt;/p&gt;&lt;p&gt;比如博客园首页加载&amp;ldquo;最新随笔列表&amp;rdquo;的应用场景，在用户打开页面时直接显示最新随笔（非ajax加载）；在用户点击页面上的&amp;ldquo;刷新&amp;rdquo;链接时，通过ajax更新&amp;ldquo;最新随笔列表&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012051607513311.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;使用ChildAciton+PartialView，在首页页面视图中只需Html.RenderAction即可。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@{ Html.RenderAction&amp;lt;AggSiteController&amp;gt;(c =&amp;gt; c.PostList(&lt;span style="color: #800080;"&gt;1&lt;/span&gt;,&lt;span style="color: #800080;"&gt;20&lt;/span&gt;)); }&lt;/div&gt;&lt;p&gt;同样的ChildAction可以直接服务于Ajax请求，实现了ChildAciton+PartialView的重用。&lt;/p&gt;&lt;p&gt;这时，我们遇到了一个问题，在RenderAction的时候需要向Action传递参数，&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html" target="_blank"&gt;之前&lt;/a&gt;实现的简陋的Html.RenderAction并没有对此提供支持，需要改进一下。&lt;/p&gt;&lt;p&gt;从&lt;a id="ctl00_CommentList_NameLink_9" href="http://home.cnblogs.com/u/137106/" rel="nofllow" target="_blank"&gt;testzhangsan&lt;/a&gt;的&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html#2377801" target="_blank"&gt;评论&lt;/a&gt;中获知，ASP.NET MVC 4中已经在实现Lamda版Html.RenderAction。签出ASP.NET MVC 4的源代码一下，果然实现了，向Action传参数的问题自然也被微软解决了。参照那段代码，精简一下就能解决我们的问题。&lt;/p&gt;&lt;p&gt;向Action传参数，需要通过RouteValueDictionary，我们所要做的工作就是从Lamda表达式中获取参数名称与参数值，并还添加至RouteValueDictionary。&lt;/p&gt;&lt;p&gt;完整代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc.Html;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Linq.Expressions;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Routing;&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc.Html&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; HtmlHelperExtensions&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; RenderAction&amp;lt;TController&amp;gt;(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt; HtmlHelper htmlHelper,&lt;br/&gt;            Expression&lt;/span&gt;&amp;lt;Action&amp;lt;TController&amp;gt;&amp;gt;&lt;span style="color: #000000;"&gt; operation)&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;where&lt;/span&gt;&lt;span style="color: #000000;"&gt; TController : Controller&lt;br/&gt;        {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; controllerName = &lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(TController).Name;&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (controllerName.EndsWith(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Controller&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br/&gt;            {&lt;br/&gt;                controllerName &lt;/span&gt;= controllerName.Substring(&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;                    controllerName.Length &lt;/span&gt;- &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Controller&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Length);&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; call = operation.Body &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; MethodCallExpression;&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (call != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;            {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; actionName =&lt;span style="color: #000000;"&gt; call.Method.Name;&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; parameters =&lt;span style="color: #000000;"&gt; call.Method.GetParameters();&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (parameters.Length &amp;gt; &lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;                {&lt;br/&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; routeValues = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; RouteValueDictionary();&lt;br/&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;; i &amp;lt; parameters.Length; i++&lt;span style="color: #000000;"&gt;)&lt;br/&gt;                    {&lt;br/&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; ce = call.Arguments[i] &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; ConstantExpression;&lt;br/&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (ce != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;                        {&lt;br/&gt;                            routeValues.Add(parameters[i].Name, ce.Value);&lt;br/&gt;                        }&lt;br/&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;                        {&lt;br/&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; lambda =&lt;span style="color: #000000;"&gt; Expression.Lambda(call.Arguments[i],&lt;br/&gt;                                                         operation.Parameters);&lt;br/&gt;                            Delegate d &lt;/span&gt;=&lt;span style="color: #000000;"&gt; lambda.Compile();&lt;br/&gt;                            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; value = d.DynamicInvoke(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;[&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;br/&gt;                            routeValues.Add(parameters[i].Name, value);&lt;br/&gt;                        }&lt;br/&gt;                        &lt;br/&gt;                    }&lt;br/&gt;                    htmlHelper.RenderAction(actionName, controllerName, routeValues);&lt;br/&gt;                }&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;                {&lt;br/&gt;                    htmlHelper.RenderAction(actionName, controllerName);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;注：目前的这个实现不支持可空类型的参数，比如：public ActionResult PostList(int? pageIndex)。&lt;/p&gt;&lt;p&gt;开源，真好！&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2502740.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/16/mvc_renderaction_lamda_2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html</id><title type="text">[ASP.NET MVC]让Html.RenderAction支持Lamda表达式</title><summary type="text">今天在ASP.NET MVC代码时用到了Html.RenderAction，通过字符串指定Action的名称，有两点不爽。有这两点不爽，写代码的乐趣就大减。微软不让我们享受，我们就自己动手，丰衣足食，自己写一个支持Lamda表达式的Html.RenderAction。Lamda，给你写代码带来畅快感觉的Lamda！</summary><published>2012-05-15T08:28:00Z</published><updated>2012-05-15T08:28:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html"/><content type="html">&lt;p&gt;今天在ASP.NET MVC代码时用到了Html.RenderAction，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@{Html.RenderAction(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RecentNews&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)}&lt;/div&gt;&lt;p&gt;通过字符串指定Action的名称，有两点不爽：&lt;/p&gt;&lt;p&gt;1. 输入时不能智能感知；&lt;/p&gt;&lt;p&gt;2. 输错了不能实时提示。&lt;/p&gt;&lt;p&gt;有这两点不爽，写代码的乐趣就大减。有享受感觉的代码应该是这样的：&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@{Html.RenderAction&amp;lt;AggSiteController&amp;gt;(c =&amp;gt; c.RecentNews());}&lt;/div&gt;&lt;p&gt;是的，Lamda，给你写代码带来畅快感觉的Lamda！&lt;/p&gt;&lt;p&gt;微软不让我们享受，我们就自己动手，丰衣足食。自己写一个支持Lamda表达式的Html.RenderAction，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc.Html;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Linq.Expressions;&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.Mvc.Html&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; HtmlHelperExtensions&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; RenderAction&amp;lt;TController&amp;gt;(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt; HtmlHelper htmlHelper, &lt;br/&gt;            Expression&lt;/span&gt;&amp;lt;Action&amp;lt;TController&amp;gt;&amp;gt;&lt;span style="color: #000000;"&gt; operation) &lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;where&lt;/span&gt;&lt;span style="color: #000000;"&gt; TController : Controller&lt;br/&gt;        {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; actionName =&lt;span style="color: #000000;"&gt; ((MethodCallExpression)operation.Body).Method.Name;&lt;br/&gt;            htmlHelper.RenderAction(actionName);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;注：其中"((MethodCallExpression)operation.Body).Method.Name"代码来自&lt;a href="http://stackoverflow.com/questions/5364520/get-method-name-from-action" target="_blank"&gt;Get Method Name From Action&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;顺带分享一篇文章&lt;a href="http://www.arrangeactassert.com/when-to-use-html-renderpartial-and-html-renderaction-in-asp-net-mvc-razor-views/" target="_blank"&gt;When to use Html.RenderPartial and Html.RenderAction in ASP.NET MVC Razor Views&lt;/a&gt;，通过这篇文章你可以清楚的知道Html.RenderPartial与Html.RenderAction之间的区别。&lt;/p&gt;&lt;p&gt;比如：博客园首页的最新随笔列表就适合用Html.RenderPartial，而右侧的&amp;ldquo;新闻列表&amp;rdquo;就适合用Html.RenderAction。&lt;/p&gt;&lt;p&gt;简单的理解就是：Html.RenderPartial用的到PartialView只用一次（虽然实际可以多次使用，但比较麻烦，每次都要传Model），Html.RenderAction用的到PartialView被多个视图使用（有自己的Action提供Model）。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2501802.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/15/html_renderaction_lamda.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html</id><title type="text">HttpClient + ASP.NET Web API, WCF之外的另一个选择</title><summary type="text">WCF的野心造成了它的庞大复杂，HTTP的单纯造就了它的简单优美。为了实现分布式Web应用，我们不得不将两者凑合在一起 —— WCF服务以HTTP绑定宿主于IIS。最近我们在实际开发中有个地方用WCF太麻烦，就小试了一下水果刀（ASP.NET Web API），感觉还不错。</summary><published>2012-05-11T01:08:00Z</published><updated>2012-05-11T01:08:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html"/><content type="html">&lt;p&gt;WCF的野心造成了它的庞大复杂，HTTP的单纯造就了它的简单优美。为了实现分布式Web应用，我们不得不将两者凑合在一起 &amp;mdash;&amp;mdash; WCF服务以HTTP绑定宿主于IIS。&lt;/p&gt;&lt;p&gt;于是有了让人晕头转向的配置、让人郁闷不已的调试，还有那ServiceContract, DataContract,&amp;nbsp;EnumMember...还有还有，&lt;a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/dudu/archive/2011/01/18/1938144.html"&gt;不要在using语句中调用WCF服务&lt;/a&gt;...&lt;/p&gt;&lt;p&gt;于是经常自问：拿着牛刀削苹果有必要吗？废话，当然没有必要，水果刀在哪里？&lt;/p&gt;&lt;p&gt;微软看着这么多人拿着牛刀削苹果，自己也看不下去了，于是，一种水果刀横空出世 &amp;mdash;&amp;mdash;&amp;nbsp;ASP.NET Web API。&lt;/p&gt;&lt;p&gt;最近我们在实际开发中有个地方用WCF太麻烦，就小试了一下水果刀，感觉还不错。&lt;/p&gt;&lt;p&gt;下面用一个简单的示例分享一下ASP.NET Web API水果刀的用法。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;服务端ASP.NET Web API的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;需要准备的工具：Visual Studio 2010, NuGet&lt;/p&gt;&lt;p&gt;1. 新建一个空的ASP.NET Web Application项目。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012051106044133.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;2. 通过NuGet添加ASP.NET Web API的引用，在NuGet中搜索时要用&amp;ldquo;AspNetWebApi&amp;rdquo;（用&lt;span&gt;&amp;ldquo;ASP.NET Web API&amp;rdquo;是搜索不到的），然后选择ASP.NET Web API(Beta)进行安装。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012051106154984.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;3. 添加Global.asax，在Application_Start中注册Web API的路由，在Global.asax.cs中添加如下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Application_Start(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, EventArgs e)&lt;br/&gt;{&lt;br/&gt;    RouteTable.Routes.MapHttpRoute(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;WebApi&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;api/{controller}/{action}/{id}&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { id =&lt;span style="color: #000000;"&gt; RouteParameter.Optional });&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;4. 添加Controllers文件夹，在其中添加类文件DemoController.cs，并让DemoController继承自ApiController。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; CNBlogsWebApiDemo.Controllers&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; DemoController : ApiController&lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;5. 添加ViewModels文件夹，在其中添加Site.cs，并定义Site。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; CNBlogsWebApiDemo.ViewModels&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Site&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; SiteId { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Title { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Uri { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;6. 给DemoController添加一个方法SiteList，并写上我们的示例代码。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; DemoController : ApiController&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; IList&amp;lt;Site&amp;gt; SiteList(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; startId, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; itemcount)&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sites = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Site&amp;gt;&lt;span style="color: #000000;"&gt;();&lt;br/&gt;        sites.Add(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Site { SiteId = &lt;span style="color: #800080;"&gt;1&lt;/span&gt;, Title = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;test&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Uri = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;www.cnblogs.cc&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;        sites.Add(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Site { SiteId = &lt;span style="color: #800080;"&gt;2&lt;/span&gt;, Title = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;博客园首页&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Uri = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;www.cnblogs.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;        sites.Add(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Site { SiteId = &lt;span style="color: #800080;"&gt;3&lt;/span&gt;, Title = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;博问&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Uri = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;q.cnblogs.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;        sites.Add(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Site { SiteId = &lt;span style="color: #800080;"&gt;4&lt;/span&gt;, Title = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;新闻&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Uri = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;news.cnblogs.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;        sites.Add(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Site { SiteId = &lt;span style="color: #800080;"&gt;5&lt;/span&gt;, Title = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;招聘&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, Uri = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;job.cnblogs.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; result = (&lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; Site site &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt; sites&lt;br/&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; site.SiteId &amp;gt;&lt;span style="color: #000000;"&gt; startId&lt;br/&gt;                        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;span style="color: #000000;"&gt; site)&lt;br/&gt;                        .Take(itemcount)&lt;br/&gt;                        .ToList();&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; result;&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;7. 配置一下Web项目的启动设置Specific Page与Specific port&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012051106481414.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;8. Ctrl+F5运行项目，结果如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012051106511559.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;结果是我们期望的，用浏览器直接可以查看Web API的运行结果，测试时会很方便。&lt;/p&gt;&lt;p&gt;好了，服务端Web API就这么轻松搞定了！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;客户端通过HttpClient调用服务端Web API&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;1. 新建一个WebApiTest的类库项目。&lt;/p&gt;&lt;p&gt;2. 在NuGet中添加System.Net.Http(HttpClient就在这里), Json.NET, xUnit.net。&lt;/p&gt;&lt;p&gt;3. 添加类文件WebApiClientTest.cs，添加测试方法WebApi_SiteList_Test：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebApiClientTest&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebApiClientTest&lt;br/&gt;    {&lt;br/&gt;        [Fact]&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebApi_SiteList_Test()&lt;br/&gt;        {&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;4.&amp;nbsp;WebApi_SiteList_Test() 的代码实现&lt;/p&gt;&lt;p&gt;4.1 首先，要确定三个东西：&lt;/p&gt;&lt;p&gt;a) 客户端调用WebAPI的方式是Http Get，还Http Post，我们这里选用Http Post；&lt;/p&gt;&lt;p&gt;b)&amp;nbsp;客户端调用WebAPI时传递的参数格式，我们这里选用的是Json。&lt;/p&gt;&lt;p&gt;c)&amp;nbsp;WebAPI返回的数据格式，我们这里选用的也是Json（这也是之前添加Json.NET引用的原因）。&lt;/p&gt;&lt;p&gt;4.2 用到的类&lt;/p&gt;&lt;ul&gt;&lt;li&gt;System.Net.Http.HttpClient&lt;/li&gt;&lt;li&gt;System.Net.Http.httpContent&lt;/li&gt;&lt;li&gt;System.Net.Http.StringContent&lt;/li&gt;&lt;li&gt;System.Net.Http.Headers.MediaTypeHeaderValue&lt;/li&gt;&lt;li&gt;Newtonsoft.Json.JsonConvert&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;4.3 准备需要传递给WebAPI的参数&lt;/p&gt;&lt;p&gt;需要传递的两个参数是startId ,itemcount，传递的格式是Json。这里可没有Javascript中的JSON.stringify()，但我们有Json.NET，再加上匿名类型，有点用js的感觉，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; requestJson = JsonConvert.SerializeObject(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { startId = &lt;span style="color: #800080;"&gt;1&lt;/span&gt;, itemcount = &lt;span style="color: #800080;"&gt;3&lt;/span&gt; });&lt;/div&gt;&lt;p&gt;代码的运行结果：{"startId":1,"itemcount":3}&lt;/p&gt;&lt;p&gt;然后用System.Net.Http.StringContent把它打个包：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;HttpContent httpContent = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; StringContent(requestJson);&lt;/div&gt;&lt;p&gt;然后设置一下ContentType：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;httpContent.Headers.ContentType = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MediaTypeHeaderValue(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/json&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;/div&gt;&lt;p&gt;4.4 通过Http Post调用WebAPI得到返回结果&lt;/p&gt;&lt;p&gt;HttpClient闪亮登场，调用它的PostAsync()方法轻松搞定：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; httpClient = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; HttpClient();&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; responseJson = httpClient.PostAsync(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://localhost:9000/api/demo/sitelist&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, httpContent)&lt;br/&gt;    .Result.Content.ReadAsStringAsync().Result;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;看一下responseJson的结果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;[{"SiteId":2,"Title":"博客园首页","Uri":"www.cnblogs.com"},{"SiteId":3,"Title":"博问","Uri":"q.cnblogs.com"},{"SiteId":4,"Title":"新闻","Uri":"news.cnblogs.com"}]&lt;/div&gt;&lt;p&gt;正宗的Json！你注意到没有，服务端WebAPI的代码未作任何修改，我们只是在Http Headers中将ContentType设置为了application/json，返回的就是Json格式的数据。而我们通过浏览器访问，得到的还是标准的XML。这里就是ASP.NET Web API的魅力之一 &amp;mdash;&amp;mdash; 一次实现，按需服务。&lt;/p&gt;&lt;p&gt;4.5 将Json格式返回的结果反序列化为强类型&lt;/p&gt;&lt;p&gt;Json.NET又登场：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sites = JsonConvert.DeserializeObject&amp;lt;IList&amp;lt;Site&amp;gt;&amp;gt;(responseJson);&lt;/div&gt;&lt;p&gt;展示一下返回结果：&lt;/p&gt;&lt;p&gt;代码&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;sites.ToList().ForEach(x =&amp;gt; Console.WriteLine(x.Title + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;：&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + x.Uri));&lt;/div&gt;&lt;p&gt;结果&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;  博客园首页：www.cnblogs.com&lt;br/&gt;  博问：q.cnblogs.com&lt;br/&gt;  新闻：news.cnblogs.com&lt;/span&gt;&lt;/div&gt;&lt;p&gt;4.6&amp;nbsp;WebApi_SiteList_Test() 完整实现代码&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebApiClientTest&lt;br/&gt;{&lt;br/&gt;    [Fact]&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebApi_SiteList_Test()&lt;br/&gt;    {            &lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; requestJson = JsonConvert.SerializeObject(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { startId = &lt;span style="color: #800080;"&gt;1&lt;/span&gt;, itemcount = &lt;span style="color: #800080;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt; });&lt;br/&gt;&lt;br/&gt;        HttpContent httpContent &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StringContent(requestJson);&lt;br/&gt;        httpContent.Headers.ContentType &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MediaTypeHeaderValue(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/json&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; httpClient = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; HttpClient();&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; responseJson = httpClient.PostAsync(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://localhost:9000/api/demo/sitelist&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, httpContent)&lt;br/&gt;            .Result.Content.ReadAsStringAsync().Result;&lt;br/&gt;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sites = JsonConvert.DeserializeObject&amp;lt;IList&amp;lt;Site&amp;gt;&amp;gt;&lt;span style="color: #000000;"&gt;(responseJson);&lt;br/&gt;&lt;br/&gt;        sites.ToList().ForEach(x &lt;/span&gt;=&amp;gt; Console.WriteLine(x.Title + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;：&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; +&lt;span style="color: #000000;"&gt; x.Uri));&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;注：运行这里的代码之前，要先运行WebAPI项目，先把服务跑起来，客户端才能享受到服务。&lt;/p&gt;&lt;p&gt;与jQuery ajax调用代码比较一下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; requestJson = JSON.stringify({ startId: 1, itemcount: 3&lt;span style="color: #000000;"&gt; });&lt;br/&gt;$.ajax({&lt;br/&gt;    url: &lt;/span&gt;'/api/demo/sitelist'&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    data: requestJson,&lt;br/&gt;    type: &lt;/span&gt;"post"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    dataType: &lt;/span&gt;"json"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    contentType: &lt;/span&gt;"application/json; charset=utf8"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    success: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (data) {&lt;br/&gt;        jQuery.each(data, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (i, val) {&lt;br/&gt;            $(&lt;/span&gt;"#result").append(val.Title + '： ' + val.Uri +'&amp;lt;br/&amp;gt;'&lt;span style="color: #000000;"&gt;);&lt;br/&gt;        });&lt;br/&gt;    }&lt;br/&gt;});&lt;/span&gt;&lt;/div&gt;&lt;p&gt;注：上面的代码是可真实运行的哦，代码在示例代码WebApiDemo项目的AjaxWebApi.htm文件中。这也是ASP.NET Web API &amp;ldquo;一次实现，按需服务&amp;rdquo;的体现。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;小结&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;水果刀(ASP.NET Web API)用下来感觉还不错，不仅可以削苹果，还可以削梨子，切西瓜也不在话下。用不用牛刀(WCF)，还得多考虑考虑。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;示例代码下载&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/dudu/CNBlogsWebApiHttpClient.rar"&gt;http://files.cnblogs.com/dudu/CNBlogsWebApiHttpClient.rar&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;更新&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a id="ctl00_CommentList_NameLink_26" href="http://www.cnblogs.com/qgf522/" target="_blank"&gt;娃哈哈ABC&lt;/a&gt;提了一个&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html#2374864" target="_blank"&gt;很好的问题&lt;/a&gt;：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;WebApiTest引用了WebApiDemo。实现了强类型，这样还算分布式应用吗？&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;强大的Json.NET可以轻松解决这个问题，代码修改为：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;原先的代码：var sites = JsonConvert.DeserializeObject&amp;lt;IList&amp;lt;Site&amp;gt;&amp;gt;(responseJson);&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sites =&lt;span style="color: #000000;"&gt; JArray.Parse(responseJson);&lt;br/&gt;sites.ToList().ForEach(x &lt;/span&gt;=&amp;gt; Console.WriteLine(x[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Title&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;] + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;：&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + x[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Uri&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;]));&lt;/div&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2495169.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/05/03/asp_net_mvc_ascx.html</id><title type="text">ASP.NET MVC中加载WebForms用户控件(.ascx)</title><summary type="text">博客园博客中的日历用的是ASP.NET WebForms的日历控件，它会为“上一月”、“下一月”的链接生成"__doPostBack()"的js调用。要解决的问题是如何在ASP.NET MVC Controller中加载包含WebForms日历控件的用户控件，并得到其输出的字符串，然后将__doPostBack的代码替换为ajax调用代码。</summary><published>2012-05-03T04:30:00Z</published><updated>2012-05-03T04:30:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/05/03/asp_net_mvc_ascx.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/05/03/asp_net_mvc_ascx.html"/><content type="html">&lt;p&gt;&lt;strong&gt;问题背景&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;博客园博客中的日历用的是ASP.NET WebForms的日历控件（System.Web.UI.WebControls.Calendar），它会为&amp;ldquo;上一月&amp;rdquo;、&amp;ldquo;下一月&amp;rdquo;的链接生成"__doPostBack()"的js调用，如下图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012050311452677.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;目前发现它会带来两个问题：&lt;/p&gt;&lt;p&gt;1. 不支持IE10；&lt;/p&gt;&lt;p&gt;2. 某些电脑不允许执行__doPostBack。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题提炼&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;前提：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;我们想以最低的成本解决这个问题，也就是对当前代码尽可能少的改动。所以要尽可能重用现有的日历控件代码。&lt;/li&gt;&lt;li&gt;日历改为Ajax加载，点击&amp;ldquo;上一月&amp;rdquo;、&amp;ldquo;下一月&amp;rdquo;时Ajax更新日历内容。&lt;/li&gt;&lt;li&gt;用ASP.NET MVC处理Ajax请求。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;要解决的问题：&lt;/p&gt;&lt;p&gt;如何在ASP.NET MVC Controller中加载包含WebForms日历控件的用户控件（.ascx），并得到其输出的字符串，然后将__doPostBack的代码替换为ajax调用代码。&lt;/p&gt;&lt;p&gt;核心问题：&lt;/p&gt;&lt;p&gt;如何在ASP.NET MVC Controller中得到用户控件（.ascx）输出的字符串。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;解决方法&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;先看代码&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult Calendar()&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; page = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Page();&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; form = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; HtmlForm();&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; calendar = page.LoadControl(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Controls/CNBlogsCalendar.ascx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;    form.Controls.Add(calendar);&lt;br/&gt;    page.Controls.Add(form);&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sw = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StringWriter())&lt;br/&gt;    {&lt;br/&gt;        System.Web.HttpContext.Current.Server.Execute(page, sw, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; Content(sw.ToString());&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;代码很简单，但得到这个代码花了今天一上午时间。&lt;/p&gt;&lt;p&gt;代码说明：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;必须要new Page()，只有Page才能LoadControl。&lt;/li&gt;&lt;li&gt;必须要new HtmlForm()，因为日历控件必要要放在&amp;lt;form runat="server"&amp;gt;之间。&lt;/li&gt;&lt;li&gt;关键功臣是HttpContext.Current.Server.Execute，动态加载控件并输出字符串全靠它。这个功臣是在&lt;a href="http://samuelmueller.com/2008/12/dynamicloader-plugin-dynamically-loading-asp-net-user-controls-with-jquery/" target="_blank"&gt;这篇文章&lt;/a&gt;中找到的（感谢Sam Mueller）。之前我用过的方法（&lt;a href="http://www.cnblogs.com/dudu/archive/2011/03/19/asp_net_mvc_user_control.html" target="_blank"&gt;继续不走寻常路：ASP.NET MVC中使用Web Forms用户控件&lt;/a&gt;）不仅麻烦，而且在这个场景下会有问题。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;代码运行结果：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012050312225569.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;完整代码下载：&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/dudu/CNBlogsDemoMvcAscx.rar"&gt;http://files.cnblogs.com/dudu/CNBlogsDemoMvcAscx.rar&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2480424.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/03/asp_net_mvc_ascx.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/30/asp_net_mvc_google_oauth_api.html</id><title type="text">ASP.NET MVC通过OAuth调用Google API获取用户信息</title><summary type="text">一边享受着乡村的宁静，一边写着博客，也是一种惬意。喜欢解决问题后写一篇博客。通过文字表达出来，会加深自己的理解，还经常会有新的收获，甚至会找到更好的解决方法。同时，还能分享给别人。一举多得，何乐而不为呢？这次要解决的问题是如何在用户注册时验证用户的邮箱？</summary><published>2012-04-30T05:59:00Z</published><updated>2012-04-30T05:59:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/30/asp_net_mvc_google_oauth_api.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/30/asp_net_mvc_google_oauth_api.html"/><content type="html">&lt;p&gt;一边享受着乡村的宁静，一边写着博客，也是一种惬意。&lt;/p&gt;&lt;p&gt;喜欢解决问题后写一篇博客。通过文字表达出来，会加深自己的理解，还经常会有新的收获，甚至会找到更好的解决方法。同时，还能分享给别人。一举多得，何乐而不为呢？&lt;/p&gt;&lt;p&gt;这次要解决的问题是&lt;strong&gt;如何在用户注册时验证用户的邮箱？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通常的解决方法是给用户的邮箱发一封激活邮件。但这个方法有以下几个问题：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;从发出邮件至收到邮件，可能会有延时。&lt;/li&gt;&lt;li&gt;邮件可能会被当作垃圾邮件处理&lt;/li&gt;&lt;li&gt;用户可能会填错了邮箱，更糟糕的情况是用户不知道自己填错了邮箱。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这次要解决的问题的更具体的场景是如何验证用户的gmail邮箱？&lt;/p&gt;&lt;p&gt;我们采用的解决方法是&lt;strong&gt;通过OAuth调用Google API获取用户的gmail地址&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;&lt;a href="http://oauth.net/2/" target="_blank"&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012043009043235.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;于是，问题就变为&lt;strong&gt;如何在ASP.NET MVC中通过OAuth调用Google API&lt;/strong&gt;？&lt;/p&gt;&lt;p&gt;必看的两个文档：&lt;/p&gt;&lt;p&gt;&lt;a href="https://developers.google.com/accounts/docs/OAuth2WebServer" target="_blank"&gt;Using OAuth 2.0 to Access Google APIs&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://developers.google.com/accounts/docs/OAuth2WebServer" target="_blank"&gt;Using OAuth 2.0 for Web Server Applications&lt;/a&gt;&lt;/p&gt;&lt;p&gt;我们的OAuth应用场景是Web Server Applications，对应的序列图如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012043009081916.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;简单描述一下整个流程：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;你在网站上提供一个Google OAuth登录的链接&lt;/li&gt;&lt;li&gt;用户点击这个链接进入Google登录页面进行登录&lt;/li&gt;&lt;li&gt;用户登录成功后，会显示授权页面。&lt;/li&gt;&lt;li&gt;用户授权成功后，Google会自动重定向至你的网站页面，并传递authorization code给你。&lt;/li&gt;&lt;li&gt;通过这个authorization code，向Google OAuth服务器请求access_token。&lt;/li&gt;&lt;li&gt;拿到access_token之后，调用Google API获取用户信息。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;下面是具体的实现步骤：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;1. 进入&lt;a href="https://code.google.com/apis/console#access" target="_blank"&gt;Google APIs Console&lt;/a&gt;，创建一个Project，并创建Client ID，如下图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012043010290658.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;得到这些信息 &amp;mdash;&amp;mdash;&amp;nbsp;Client ID, Email address, Client secret, Redirect URIs&lt;/p&gt;&lt;p&gt;2. 创建一个空的ASP.NET MVC项目&lt;/p&gt;&lt;p&gt;3. 在web.config中添加相应的appSetting保存第1步得到的Client ID相关信息&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ClientID"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=""&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="EmailAddress"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=""&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ClientSecret"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=""&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;        &lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="RedirectURI"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=""&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;      &lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;4. 创建MVC控制器OAuthController，并添加名为GoogleLogin的Action，用于重定向至Google页面进行登录。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; OAuthController : Controller&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult GoogleLogin()&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; url = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://accounts.google.com/o/oauth2/auth?&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;+&lt;br/&gt;            &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;scope={0}&amp;amp;state={1}&amp;amp;redirect_uri={2}&amp;amp;response_type=code&amp;amp;client_id={3}&amp;amp;approval_prompt=force&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;userinfo.email表示获取用户的email&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; scope = HttpUtility.UrlEncode(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://www.googleapis.com/auth/userinfo.email&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;对应于userinfo.email&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; state = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;email&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; redirectUri = HttpUtility.UrlEncode(ConfigurationManager.AppSettings[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RedirectURI&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; cilentId = HttpUtility.UrlEncode(ConfigurationManager.AppSettings[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ClientID&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Redirect(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Format(url, scope, state, redirectUri, cilentId));&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;编译后，通过浏览器访问，假设域名是passport.cnblogs.cc，访问网址就是passport.cnblogs.cc/oauth/googlelogin，访问后，如果你的google帐户已经处于登录状态，则直接显示授权页面，如下图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012043011135288.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;点击"Allow access"之后，页面会被重定向回你的网站，我们这里重定向过来的网址是passport.cnblogs.cc/oauth2callback?state=email&amp;amp;code=4/BSCUqsaY6S5GYk9tFR-45-_UhL4-，查询参数code的值就是authorization code，接下来就是对这个重定向网址passport.cnblogs.cc/oauth2callback的处理（这个网址就是第1步中得到的Redirect URIs）。&lt;/p&gt;&lt;p&gt;5. 在Global.asax.cs中添加路由规则，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;routes.MapRoute(&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;oauth2callback&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;oauth2callback&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { controller = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OAuth&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, action = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GoogleCallback&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, id =&lt;span style="color: #000000;"&gt; UrlParameter.Optional }&lt;br/&gt;);&lt;/span&gt;&lt;/div&gt;&lt;p&gt;6. 在OAuthController中添加名为GoogleCallback的Action&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; OAuthController : Controller&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult GoogleCallback()&lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;接下来的操作都在GoogleCallback()中完成。&lt;/p&gt;&lt;p&gt;7. &amp;nbsp;这一步是关键的地方，主要完成两个操作：&lt;/p&gt;&lt;p&gt;a) 通过authorization code，向Google OAuth服务器请求access_token（访问令牌，每次调用Google API都需要这个）。&lt;br /&gt;b) 拿到access_token之后，调用Google API获取用户信息（这里是email）。&lt;/p&gt;&lt;p&gt;主要参考文档：&lt;a href="https://developers.google.com/accounts/docs/OAuth2WebServer"&gt;https://developers.google.com/accounts/docs/OAuth2WebServer&lt;/a&gt;&lt;/p&gt;&lt;p&gt;7.1 根据authorization code获取access_token的代码流程是：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;向https://accounts.google.com/o/oauth2/token发送HTTP POST请求，并传递相应的参数。&lt;/li&gt;&lt;li&gt;获取服务器的响应，响应内容的格式时json格式。&lt;/li&gt;&lt;li&gt;将json反序列化为匿名类型的实例，并获取access_token。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;由于是https，这里必须要转换为HttpWebRequest&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; webRequest = WebRequest.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://accounts.google.com/o/oauth2/token&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; HttpWebRequest;&lt;br/&gt;webRequest.Method &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;POST&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;webRequest.ContentType &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;参考https:&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;developers.google.com/accounts/docs/OAuth2WebServer&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; postData = &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;code={0}&amp;amp;client_id={1}&amp;amp;client_secret={2}&amp;amp;redirect_uri={3}&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; +&lt;br/&gt;    &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;amp;grant_type=authorization_code&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;code&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;],&lt;br/&gt;        ConfigurationManager.AppSettings[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ClientID&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;],&lt;br/&gt;        ConfigurationManager.AppSettings[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ClientSecret&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;],&lt;br/&gt;        ConfigurationManager.AppSettings[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RedirectURI&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;在HTTP POST请求中传递参数&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sw = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamWriter(webRequest.GetRequestStream()))&lt;br/&gt;{&lt;br/&gt;    sw.Write(postData);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;发送请求，并获取服务器响应&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; resonseJson = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; response =&lt;span style="color: #000000;"&gt; webRequest.GetResponse())&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sr = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamReader(response.GetResponseStream()))&lt;br/&gt;    {&lt;br/&gt;        resonseJson &lt;/span&gt;=&lt;span style="color: #000000;"&gt; sr.ReadToEnd();&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Json.NET对服务器返回的json字符串进行反序列化，得到access_token&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; accessToken = JsonConvert.DeserializeAnonymousType(resonseJson, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { access_token = &lt;span style="color: #800000;"&gt;""&lt;/span&gt; }).access_token;&lt;/div&gt;&lt;p&gt;7.2&amp;nbsp;根据access_token读取用户信息的代码流程是：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;向https://www.googleapis.com/oauth2/v1/userinfo发送HTTP GET请求，在请求头中包含access_token信息。&lt;/li&gt;&lt;li&gt;获取服务器的json格式的响应内容，并从中读取用户的email信息。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;webRequest = WebRequest.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://www.googleapis.com/oauth2/v1/userinfo&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; HttpWebRequest;&lt;br/&gt;webRequest.Method &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GET&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;webRequest.Headers.Add(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Authorization&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Bearer &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; +&lt;span style="color: #000000;"&gt; accessToken);&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; response =&lt;span style="color: #000000;"&gt; webRequest.GetResponse())&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sr = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamReader(response.GetResponseStream()))&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Content(JsonConvert.DeserializeAnonymousType(sr.ReadToEnd(), &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; { Email = &lt;span style="color: #800000;"&gt;""&lt;/span&gt;&lt;span style="color: #000000;"&gt; }).Email);&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;完整代码下载&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/dudu/CNBlogsDemoMvcOAuth.rar"&gt;http://files.cnblogs.com/dudu/CNBlogsDemoMvcOAuth.rar&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2476898.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/30/asp_net_mvc_google_oauth_api.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/28/webrequest_post_google_oauth.html</id><title type="text">ASP.NET/C#  WebRequest POST Google OAuth API</title><summary type="text">这篇文章主要是分享一段代码，解决的问题是：通过 WebRequest 向 https://accounts.google.com/o/oauth2/token 发起 HTTP POST 请求，根据 authorization code 获取 access_token。</summary><published>2012-04-28T14:29:00Z</published><updated>2012-04-28T14:29:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/28/webrequest_post_google_oauth.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/28/webrequest_post_google_oauth.html"/><content type="html">&lt;p&gt;这篇文章主要是分享一段代码，解决的问题是：通过&amp;nbsp;WebRequest 向&amp;nbsp;https://accounts.google.com/o/oauth2/token&amp;nbsp;发起 HTTP POST 请求，根据&amp;nbsp;authorization code 获取&amp;nbsp;access_token。&lt;/p&gt;&lt;p&gt;C#代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult GoogleOAuthCallback()&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; webRequest = WebRequest.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://accounts.google.com/o/oauth2/token&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; HttpWebRequest;&lt;br/&gt;    webRequest.Method &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;POST&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    webRequest.ContentType &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; postData = &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;code={0}&amp;amp;client_id={1}&amp;amp;client_secret={2}&amp;amp;redirect_uri={3}&amp;amp;grant_type=authorization_code&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;        Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;code&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;],&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Client ID&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Client secret&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Redirect URIs&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;(&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sw = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamWriter(webRequest.GetRequestStream()))&lt;br/&gt;    {&lt;br/&gt;        sw.Write(postData);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; response =&lt;span style="color: #000000;"&gt; webRequest.GetResponse())&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; sr = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamReader(response.GetResponseStream()))&lt;br/&gt;        {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; Content(sr.ReadToEnd());&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2475775.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/28/webrequest_post_google_oauth.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/27/jquery_validate_unobtrusive_focusout_focusin.html</id><title type="text">ASP.NET MVC Unobtrusive JavaScript 实现 onfocusout 验证, onfocusin 清除错误</title><summary type="text">默认情况下，jquery.validate.unobtrusive只在点击表单提交按钮时才触发验证，验证出错时，光标移入输入框不会清除错误提示信息。而我们的需求时，只要光标移出输入框（onfocusout）就触发验证，光标移入输入框（onfocusin）时清除错误信息。</summary><published>2012-04-27T05:43:00Z</published><updated>2012-04-27T05:43:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/27/jquery_validate_unobtrusive_focusout_focusin.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/27/jquery_validate_unobtrusive_focusout_focusin.html"/><content type="html">&lt;p&gt;在 ASP.NET MVC 中启用 Unobtrusive JavaScript 功能，可以在运行时由服务器端根据Model中设置的验证规则，自动生成客户端验证js代码（结合jquery.validate）。这很好地解决了表单验证时一次代码，两次验证（客户端+服务器端）的问题。&lt;/p&gt;&lt;p&gt;使用它很简单，主要操作步骤如下：&lt;/p&gt;&lt;p&gt;1. 在web.config增加如下设置：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ClientValidationEnabled"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;add &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;key&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="UnobtrusiveJavaScriptEnabled"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="true"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;appSettings&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;2. 在NuGet中引用jquery.validate与jquery.validate.unobtrusive&lt;/p&gt;&lt;p&gt;3. 在页面中添加js引用：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/scripts/jquery.validate.min.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;       &lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/scripts/jquery.validate.unobtrusive.min.js"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;4. 在model中添加验证规则，示例代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; SignupUser&lt;br/&gt;{&lt;br/&gt;    [Required(ErrorMessageResourceName &lt;/span&gt;= &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;DefaultRequireErrorMsg&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;        ErrorMessageResourceType &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(Resources))]&lt;br/&gt;    [DataType(DataType.EmailAddress)]&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Email { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;5. 在页面中添加表单生成代码，比如：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;@using(Html.BeginForm())&lt;br/&gt;{   &lt;br/&gt;    @Html.LabelFor(m&lt;/span&gt;=&amp;gt;&lt;span style="color: #000000;"&gt;m.Email)&lt;br/&gt;    @Html.TextBoxFor(m&lt;/span&gt;=&amp;gt;&lt;span style="color: #000000;"&gt;m.Email)&lt;br/&gt;    @Html.ValidationMessageFor(m&lt;/span&gt;=&amp;gt;&lt;span style="color: #000000;"&gt;m.Email)           &lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;参考文章：&lt;a href="http://www.cnblogs.com/dozer/archive/2010/11/11/Unobtrusive-JavaScript-in-ASP-NET-MVC-3.html" target="_blank"&gt;Unobtrusive JavaScript in ASP.NET MVC 3&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;进入正题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;默认情况下，jquery.validate.unobtrusive只在点击表单提交按钮时才触发验证，验证出错时，光标移入输入框不会清除错误提示信息（jquery.validate也一样，unobtrusive只是jquery.validate的一个扩展）。&lt;/p&gt;&lt;p&gt;而我们的需求是，只要光标移出输入框（onfocusout）就触发验证，光标移入输入框（onfocusin）时清除错误信息。&lt;/p&gt;&lt;p&gt;效果如下：&lt;/p&gt;&lt;p&gt;1.&amp;nbsp;光标移出（onfocusout）时&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012042713162971.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;2.&amp;nbsp;光标移入（onfocusin）时&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012042713182092.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;如何解决这个问题呢？&lt;/p&gt;&lt;p&gt;解决方法是简单的，找到解决方法的过程是曲折的。&lt;/p&gt;&lt;p&gt;jquery.validate对这个需求并没有提供很好的支持，需要研究它的代码，接管onfocusout与onfocusin的事件处理，并屏蔽onkeyup的事件处理。最终解决问题的代码如下：&lt;/p&gt;&lt;p&gt;针对jquery.validate.unobtrusive：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;$.validator.setDefaults({&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;光标移出时&lt;/span&gt;&lt;br/&gt;    onfocusout: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.element(element);&lt;br/&gt;    },&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;光标移入时&lt;/span&gt;&lt;br/&gt;    onfocusin: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element, event) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;找到显示错误提示的标签并移除,针对jquery.validate.unobtrusive&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; errorElement = $(element).next('span.field-validation-error'&lt;span style="color: #000000;"&gt;);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (errorElement) {&lt;br/&gt;            errorElement.children().remove();&lt;br/&gt;        }&lt;br/&gt;    },&lt;br/&gt;    onkeyup: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element, event) {&lt;br/&gt;    }&lt;br/&gt;});&lt;/span&gt;&lt;/div&gt;&lt;p&gt;如果没有使用jquery.validate.unobtrusive，想在jquery.validate中实现同样的效果，对应的代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;$.validator.setDefaults({&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;光标移出时&lt;/span&gt;&lt;br/&gt;    onfocusout: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.element(element);&lt;br/&gt;    },&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;光标移入时&lt;/span&gt;&lt;br/&gt;    onfocusin: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element, event) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;仅针对jquery.validate&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; errorElement = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.errorsFor(element);&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (errorElement) {&lt;br/&gt;            errorElement.remove();&lt;br/&gt;        }&lt;br/&gt;    },&lt;br/&gt;    onkeyup: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (element, event) {&lt;br/&gt;    }&lt;br/&gt;});&lt;/span&gt;&lt;/div&gt;&lt;p&gt;好了，这篇博文就是为了分享一下自己摸索出来的解决方法。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;相关博问：&lt;a class="blacklink" href="http://q.cnblogs.com/q/35438/"&gt;ASP.NET MVC 表单验证用什么好&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2473288.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/27/jquery_validate_unobtrusive_focusout_focusin.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/14/ie9_bug_textarea.html</id><title type="text">IE9 bug: 在textarea中复制内容会丢失换行符</title><summary type="text">在IE9中，在HTML多行文本框textarea中输入带有换行的内容，然后选中文本框中的内容Ctrl+C/Ctrl+V粘贴到记事本中，所有换行符会丢失，变成一行。经过测试，在IE6, IE8, Chrome, Firefox中都不存在这个问题。</summary><published>2012-04-14T12:39:00Z</published><updated>2012-04-14T12:39:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/14/ie9_bug_textarea.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/14/ie9_bug_textarea.html"/><content type="html">&lt;p&gt;这是我们在实际开发中实实在在遇到的问题，没有任何悬念。这个问题就是：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;在IE9中，在HTML多行文本框textarea中输入带有换行的内容，比如在这篇随笔下面的评论框中输入，然后选中文本框中的内容Ctrl+C/Ctrl+V粘贴到记事本中，所有换行符会丢失，变成一行。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;经过测试，在IE6, IE8, Chrome, Firefox中都不存在这个问题。&lt;/p&gt;&lt;p&gt;stackoverflow上也提到了这个问题 -&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/5598271/ie9-and-textarea-newlines" target="_blank"&gt;IE9 and TEXTAREA newlines&lt;/a&gt;，并提供了你轻意不会采用的解决方法，就是让IE9倒退至IE7，在&amp;lt;head&amp;gt;中添加如下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color: #008000;"&gt; Mimic Internet Explorer 7 &lt;/span&gt;&lt;span style="color: #008000;"&gt;--&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;meta &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;http-equiv&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="X-UA-Compatible"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; content&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="IE=EmulateIE7"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;一个很小的问题，却给我们实现一个功能带来了大麻烦！&lt;/p&gt;&lt;p&gt;园子里找了找，&lt;a href="http://www.cnblogs.com/huajs/"&gt;huajs&lt;/a&gt;还发现了IE9的另外一个bug（详见&lt;a href="http://www.cnblogs.com/huajs/archive/2011/11/06/2238326.html" target="_blank"&gt;发现了IE9里的一个bug&lt;/a&gt;），也是针对textarea的，这里也拿出来示众一下。&lt;/p&gt;&lt;p&gt;简而言之，就是IE9会解析textarea中的html代码，测试代码如下（&lt;a href="http://www.cnblogs.com/huajs/archive/2011/11/06/2238326.html" target="_blank"&gt;代码来源&lt;/a&gt;）：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;DOCTYPE HTML&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;textarea &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="t"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; rows&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="6"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;textarea&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; t &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; document.getElementById(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;t&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br/&gt;t.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&amp;lt;p style='color:red'&amp;gt;aaaa&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;  &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 只能在IE9中被解析，其他浏览器不解析&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br/&gt;/*&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;下边是我自己测试的结论：&lt;br/&gt; textarea表示文本区域，本应该把它里边的各种文字、标签等显示成纯文本的形式。&lt;br/&gt;    直接把诸如&lt;br/&gt;    &amp;lt;p style='color:red'&amp;gt;aa&amp;lt;/p&amp;gt;的html形式标签放到textarea里，在IE9及其他浏览器里都会把P标签显示出来，&lt;br/&gt;    这个应该是正确的解析，没什么问题。&lt;br/&gt;    但是，把&lt;br/&gt;    &amp;lt;p style='color:red'&amp;gt;aa&amp;lt;/p&amp;gt;&lt;br/&gt;    通过JS的innerHTML向textarea里插入，就能（只能）被IE9解析成红色的aa，把p标签当成html标签解析，&lt;br/&gt;    p被过滤掉了（注意，&amp;lt;!DOCTYPE&amp;gt;的文档声明必须要加上，不加的话，IE9就不会解析p标签了）。&lt;br/&gt;    当然，textarea里一般不应该用innerHTML方法插入内容。&lt;br/&gt;    &lt;br/&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;*/&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2447551.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/14/ie9_bug_textarea.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/13/entity_framework_include_where.html</id><title type="text">Entity Framework 使用注意：Where查询条件中用到的关联实体不需要Include</title><summary type="text">来自博客园开发团队开发前线最新消息：在EF中，如果实体A关联了实体B，你想在加载实体A的同时加载实体B。通常做法是在LINQ查询中使用Include()。但是，如果你在查询条件中用到了实体B，EF会自动加载实体B，这时Include不仅是多余的，而且还会增加额外的LEFT OUTER JOIN查询，影响性能。</summary><published>2012-04-13T09:36:00Z</published><updated>2012-04-13T09:36:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/13/entity_framework_include_where.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/13/entity_framework_include_where.html"/><content type="html">&lt;p&gt;来自博客园开发团队开发前线最新消息：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;在Entity Framework中，如果实体A关联了实体B，你想在加载实体A的同时加载实体B。通常做法是在LINQ查询中使用Include()。但是，如果你在查询条件中用到了实体B，EF会自动加载实体B，这时Include不仅是多余的，而且还会增加额外的LEFT OUTER JOIN查询，影响性能。&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;请看我们在&lt;a href="http://q.cnblogs.com/" target="_blank"&gt;博问&lt;/a&gt;开发中遭遇这个问题时的一段代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;For q.cnblogs.com&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; QuestionService &lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; IRepository&amp;lt;QuestionItem&amp;gt;&lt;span style="color: #000000;"&gt; _questionRepository;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; QuestionService(IUnitOfWork unitOfWork)&lt;br/&gt;        : &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;(unitOfWork)&lt;br/&gt;    {&lt;br/&gt;        _questionRepository &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Repository&amp;lt;QuestionItem&amp;gt;&lt;span style="color: #000000;"&gt;(unitOfWork);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; List&amp;lt;QuestionItem&amp;gt; GetUnsolvedQuestions(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; pageIndex, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; pageSize)&lt;br/&gt;    {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; _questionRepository.Entities&lt;br/&gt;            .Include(q &lt;/span&gt;=&amp;gt;&lt;span style="color: #000000;"&gt; q.User)&lt;br/&gt;            .Where(q &lt;/span&gt;=&amp;gt; q.IsActive &amp;amp;&amp;amp;&lt;span style="color: #000000;"&gt; q.User.IsActive)&lt;br/&gt;            .Skip((pageIndex &lt;/span&gt;- &lt;span style="color: #800080;"&gt;1&lt;/span&gt;) *&lt;span style="color: #000000;"&gt; pageSize)&lt;br/&gt;            .Take(pageSize)&lt;br/&gt;            .ToList();&lt;br/&gt;            &lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; QuestionItem&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; Id { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Title { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; IsActive { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; UserId { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; User User { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; User&lt;br/&gt;{&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; UserId { &lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; IsActive {&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;}&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;在上面的代码中，我们想在GetActiveQuestions()返回List&amp;lt;QuestionItem&amp;gt;时，QuestionItem中要包含User信息，所以在LINQ查询使用了.Include(q =&amp;gt; q.User)。&lt;/p&gt;&lt;p&gt;（特别要注意的是：这里把q.&lt;strong&gt;User&lt;/strong&gt;.IsActive作为查询条件之一）&lt;/p&gt;&lt;p&gt;然后我们用SQL Server Profiler发现，Entity Framework生成了如下的SQL语句：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TOP&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;25&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Id&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Id&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Title&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Title&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;FROM&lt;/span&gt; ( &lt;span style="color: #0000ff;"&gt;SELECT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Id&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Id&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Title&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Title&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserId1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent3&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent3&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br/&gt;row_number() &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;OVER&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;ORDER&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;BY&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;QID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;DESC&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;row_number&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;FROM&lt;/span&gt;   &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;question_Item&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;INNER&lt;/span&gt; &lt;span style="color: #808080;"&gt;JOIN&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Users&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ON&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #808080;"&gt;LEFT&lt;/span&gt; &lt;span style="color: #808080;"&gt;OUTER&lt;/span&gt; &lt;span style="color: #808080;"&gt;JOIN&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Users&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent3&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ON&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent3&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;UserID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;WHERE&lt;/span&gt; (&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;) &lt;span style="color: #808080;"&gt;AND&lt;/span&gt; (&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Extent2&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;IsActive&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;br/&gt;)  &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;WHERE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;row_number&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #800000; font-weight: bold;"&gt;0&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;ORDER&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;BY&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Filter1&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Id&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;DESC&lt;/span&gt;&lt;/div&gt;&lt;p&gt;[dbo].[Users]表对应的就是User实体类，上面的SQL中[dbo].[Users]出现了两次JOIN，由于[Users]表数据量比较大，两次JOIN影响了执行计划，查询耗时增加。这显然是要避免的。&lt;/p&gt;&lt;p&gt;在与这个问题一阵激战之后，我们终于找到解决方法 &amp;mdash;&amp;mdash; 去掉Include，就这么简单！&lt;/p&gt;&lt;p&gt;从这个地方看，Entity Framework还是挺聪明的，但是由于不知道它的这个聪明之处，反而带来了问题。&lt;/p&gt;&lt;p&gt;所以，代码如人，要和她相处好，就要了解她的一切！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2446149.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/13/entity_framework_include_where.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/dudu/archive/2012/04/09/css_unselectable_uncopyable.html</id><title type="text">[Web前端]CSS实现“不可选择，不可复制”面临的问题</title><summary type="text">对于“不可选择(unselectable)”，三种浏览器虽然实现方法不一，但都能实现；对于“不可复制(uncopyable)”，只有Firefox独领风骚！-webkit-user-select: none; 一招致胜。Chrome与IE9只能另辟蹊径（目前还没辟出来）。</summary><published>2012-04-09T05:08:00Z</published><updated>2012-04-09T05:08:00Z</updated><author><name>dudu</name><uri>http://www.cnblogs.com/dudu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/dudu/archive/2012/04/09/css_unselectable_uncopyable.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/dudu/archive/2012/04/09/css_unselectable_uncopyable.html"/><content type="html">&lt;p&gt;&lt;strong&gt;问题背景&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在博客园代码高亮中，如果显示了行号，读者在复制代码时会将行号一起复制出来，要删除这些行号，代码才可用。&lt;/p&gt;&lt;p&gt;为了解决这个麻烦，我们开始采用的方法是在高亮代码下面提供一个&amp;ldquo;复制代码&amp;rdquo;链接，点击这个链接时，通过js代码删除行号。&lt;/p&gt;&lt;p&gt;这个方法欠缺之处：1. 读者不一定注意到&amp;ldquo;复制代码&amp;rdquo;链接；2. 多了一次点击操作。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;解决思路&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;读者复制代码的通常操作是鼠标拖拉选择代码内容，然后Ctrl+C进行复制。增加任何鼠标与键盘的操作，都不是好的解决方法。&lt;/p&gt;&lt;p&gt;我们想到的最简单的解决方法就是通过CSS来实现。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现过程&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;主要参考内容：&lt;a href="http://stackoverflow.com/questions/826782/css-rule-to-disable-text-selection-highlighting" target="_blank"&gt;css rule to disable text selection highlighting&lt;/a&gt;&lt;/p&gt;&lt;p&gt;测试浏览器：Firefox, Chrome, IE9&lt;/p&gt;&lt;p&gt;HTML测试代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;DOCTYPE HTML&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;meta &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;charset&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="UTF-8"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Code LineNumber Copy Test&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;style &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/css"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br/&gt;.cnblogs_code&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    background-color&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; #F5F5F5&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    font-family&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;Courier New&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    font-size&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 12px&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    border&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 1px solid #CCCCCC&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    padding&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 5px&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    overflow&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; auto&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br/&gt;.codeLineNumber&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    color&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; #008080&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;style&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="cnblogs_code"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;pre&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;iostream&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;2&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cmath&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;3&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cstring&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;4&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;vector&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;5&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cstdio&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt; &lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;pre&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;浏览器中的显示效果：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012040910474165.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #555555;"&gt;&lt;strong&gt;1. Firefox中的实现&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;1.1 css代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #800000;"&gt;.codeLineNumber&lt;/span&gt;{&lt;span style="color: #ff0000;"&gt;&lt;br/&gt;    -moz-user-select&lt;/span&gt;:&lt;span style="color: #0000ff;"&gt; none&lt;/span&gt;; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; for Firefox &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;1.2 选择效果：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012040910540766.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;注：除了行号1，其他行号都被选中了。&lt;/p&gt;&lt;p&gt;1.3 复制/粘贴效果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; #include&amp;lt;iostream&amp;gt;&lt;br/&gt;  #include&amp;lt;cmath&amp;gt;&lt;br/&gt;  #include&amp;lt;cstring&amp;gt;&lt;br/&gt;  #include&amp;lt;vector&amp;gt;&lt;br/&gt;  #include&amp;lt;cstdio&amp;gt; &lt;/div&gt;&lt;p&gt;很棒！行号没有出现。在Firefox中通过css可以有效解决这个问题。唯一不足之就是选择时，除了第一个行号，其他行号都处于选中，违背了&amp;ldquo;所见即所得&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #555555;"&gt;2. Chrome中的实现&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;2.1 css代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #800000;"&gt;.codeLineNumber&lt;/span&gt;{&lt;span style="color: #ff0000;"&gt;&lt;br/&gt;    -webkit-user-select&lt;/span&gt;:&lt;span style="color: #0000ff;"&gt; none&lt;/span&gt;; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; for Chrome &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;2.2 选择效果：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012040911321665.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;注：选择效果不错！行号没有被选中，Firefox要是能有这样的效果就完美了。&lt;/p&gt;&lt;p&gt;2.3 复制/粘贴效果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#include&amp;lt;iostream&amp;gt;&lt;br/&gt; 2  #include&amp;lt;cmath&amp;gt;&lt;br/&gt; 3  #include&amp;lt;cstring&amp;gt;&lt;br/&gt; 4  #include&amp;lt;vector&amp;gt;&lt;br/&gt; 5  #include&amp;lt;cstdio&amp;gt;&lt;/div&gt;&lt;p&gt;郁闷！号称程序员最喜欢的浏览器，竟然不能实现&amp;ldquo;不可复制&amp;rdquo;。除了第一个行号，其他行号依然会被复制。&lt;/p&gt;&lt;p&gt;在Google官方论坛中有人反馈了Chrome的这个问题：&lt;a href="http://groups.google.com/a/chromium.org/group/chromium-bugs/browse_thread/thread/52722e6ebdc0892f/7fa7d2277bdd4e35?show_docid=7fa7d2277bdd4e35" target="_blank"&gt;Issue 106180 in chromium: -webkit-user-select: none; triggers text-selection of adjacent node&lt;/a&gt;，但无人理睬。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #555555;"&gt;3. IE9中的实现&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;IE9无法通过css实现，既不支持-ms-user-select: none;也不支持user-select: none;&lt;/p&gt;&lt;p&gt;目前只找到一种方法，给不可选元素加上属性：unselectable="on"。&lt;/p&gt;&lt;p&gt;3.1 HTML代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;DOCTYPE HTML&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;meta &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;charset&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="UTF-8"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Code LineNumber Copy Test&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;style &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/css"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br/&gt;.cnblogs_code&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    background-color&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; #F5F5F5&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    font-family&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;Courier New&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    font-size&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 12px&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    border&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 1px solid #CCCCCC&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    padding&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 5px&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;    overflow&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; auto&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br/&gt;.codeLineNumber&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br/&gt;color&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; #008080&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;br/&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;style&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="cnblogs_code"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;pre&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; unselectable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="on"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; 1&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;iostream&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; unselectable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="on"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; 2&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cmath&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; unselectable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="on"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; 3&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cstring&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; unselectable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="on"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; 4&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;vector&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="codeLineNumber"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; unselectable&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="on"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt; 5&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;  #include&lt;span style="color: #ff0000;"&gt;&amp;amp;lt;&lt;/span&gt;cstdio&lt;span style="color: #ff0000;"&gt;&amp;amp;gt;&lt;/span&gt; &lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;pre&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;3.2 选择效果：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/1/2012040911493978.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;3.3 复制/粘贴效果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#include&amp;lt;iostream&amp;gt;&lt;br/&gt; 2  #include&amp;lt;cmath&amp;gt;&lt;br/&gt; 3  #include&amp;lt;cstring&amp;gt;&lt;br/&gt; 4  #include&amp;lt;vector&amp;gt;&lt;br/&gt; 5  #include&amp;lt;cstdio&amp;gt;&lt;/div&gt;&lt;p&gt;继续郁闷！IE9也无法实现&amp;ldquo;不可复制&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;小结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于&amp;ldquo;不可选择(unselectable)&amp;rdquo;，三种浏览器虽然实现方法不一，但都能实现；&lt;/p&gt;&lt;p&gt;对于&amp;ldquo;不可复制(uncopyable)&amp;rdquo;，Firefox独领风骚！-webkit-user-select: none; 一招致胜。Chrome与IE9只能另辟蹊径（目前还没辟出来）。&lt;/p&gt;&lt;p&gt;美丽的Web世界，令无数程序员竟折腰；可是残酷的现实是，美丽不美丽不是Web标准说了算，而是浏览器说了算。就像你喜欢一个美丽的女孩，可是你们能不能在一起不是她说了算，而是她的父母。&lt;/p&gt;&lt;p&gt;现在开发一个Web程序，至少f需要测试三种浏览器：Chrome, Firefox, IE；IE至少测试三个版本：IE6, IE8, IE9。如果所有浏览器都支持一个标准，那天下最幸福的程序员非Web程序员莫属！&lt;/p&gt;&lt;p&gt;如果Web领域有FDA(美国食品药物管理局)这样的机构，不符合Web标准的浏览器坚决不让上市，那该多好啊！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;附&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;完整HTML文件下载：&lt;a href="http://files.cnblogs.com/dudu/css_unselectable_uncopyable.rar"&gt;http://files.cnblogs.com/dudu/css_unselectable_uncopyable.rar&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;测试高亮代码节选自：&lt;a href="http://www.cnblogs.com/myoi/archive/2012/04/07/2436402.html" target="_blank"&gt;poj 1755 Triathlon 半平面交&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/dudu/aggbug/2438730.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/dudu/archive/2012/04/09/css_unselectable_uncopyable.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
