<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>简单生活 —— Kevin Yang的博客 &#187; AspDotNet</title> <atom:link href="http://www.imkevinyang.com/tags/aspdotnet/feed" rel="self" type="application/rss+xml" /><link>http://www.imkevinyang.com</link> <description>It&#039;s all about sharing</description> <lastBuildDate>Thu, 29 Jul 2010 17:50:43 +0000</lastBuildDate> <generator>http://wordpress.org/?v=2.9.1</generator> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item><title>Asp.Net页面的编码问题</title><link>http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html</link> <comments>http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html#comments</comments> <pubDate>Fri, 27 Nov 2009 06:13:00 +0000</pubDate> <dc:creator>Kevin Yang</dc:creator> <category><![CDATA[疑难杂症]]></category> <category><![CDATA[AspDotNet]]></category> <category><![CDATA[Content-Type]]></category> <category><![CDATA[HTTP Watch]]></category> <category><![CDATA[Response]]></category> <category><![CDATA[字符集]]></category> <category><![CDATA[样式表]]></category> <category><![CDATA[编解码]]></category><guid isPermaLink="false">http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html</guid> <description><![CDATA[<h2>莫名其妙的问题</h2><p>这些天，一个客户的网站遇到了一些莫名其妙的问题。先是首页在Firefox下看正常，但是在IE上看，同个样式表文件，却有部分样式没能加载，导致导航菜单没有背景并且走位了。后来样式的问题解决了，但是又出现了一个页面上，部分文字乱码部分正常的诡异问题。</p><h2>字符编码导致的样式文件解析错误</h2><p>对于第一个问题我的第一反应是CSS样式表中部分样式存在不兼容性。但是检查了导航菜单样式的写法，没有看出来有什么特别的，都是常见的属性常见的值。但是用I&#8230;</p>]]></description> <content:encoded><![CDATA[<h2>莫名其妙的问题</h2><p>这些天，一个客户的网站遇到了一些莫名其妙的问题。先是首页在Firefox下看正常，但是在IE上看，同个样式表文件，却有部分样式没能加载，导致导航菜单没有背景并且走位了。后来样式的问题解决了，但是又出现了一个页面上，部分文字乱码部分正常的诡异问题。</p><h2>字符编码导致的样式文件解析错误</h2><p>对于第一个问题我的第一反应是CSS样式表中部分样式存在不兼容性。但是检查了导航菜单样式的写法，没有看出来有什么特别的，都是常见的属性常见的值。但是用IE自带的开发者工具看了一下出问题的元素的样式，发现和在Firebug中看到的样式居然不同。后来无意中在HTTP Watch中看了style.css文件的内容，发现注释有乱码，当即联想到以前写过的文章《<a title="文档字符集导致的脚本错误" href="http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html" target="_blank">文档字符集导致的脚本错误</a>》。当一个文档（HTML文档或是CSS文档）的文件存储字符集和浏览器解码使用的字符集不一致的时候会出现类似的问题，特别是utf-8编码过的文档却以gb2312去解码的时候，出现的问题就更诡异了。</p><p>于是我在IE上改用UTF-8去解析网页，结果果然，导航菜单的样式正常了，背景图片也正常加载了（虽然其他地方出现了一些乱码情况）。这证明了我的思路是对的。但是具体是哪个地方出了问题呢，为什么Firefox、Opera和Chrome下都没问题，偏偏就IE有问题呢？</p><p>我又仔细查看了客户给出的网页和样式文件，又分析了相关的HTTP消息，发现请求.aspx文件（出问题的网页文档）的时候，服务端返回的Content-Type是text/html;charset=gb2312，那么所有浏览器自然会以服务器返回的字符集来解析文档，这个没问题，但是<strong><font color="#008000">当网页中引用了外部资源的时候（在这里是css样式表），IE是使用当前网页的文档字符集去解析此外部资源，除非外部资源声明了编码格式（HTTP响应头中声明或是在文档最前方使用@charset声明），而Firefox、Opera和Chrome在CSS文件没有显式声明字符集的情况下，始终是以UTF-8来解码的。</font></strong></p><p>问题既然和样式相关，也就是说在使用gb2312解析该样式表的时候出现了问题，那可以猜到，样式表文件实际的存储格式是utf-8的。</p><p>为了找到具体出问题的地方，我用Notepad++——貌似手头只有这软件可以自由编解码——模拟了一下使用gb2312解码此utf-8格式的样式表的场景，发现了其中一段出问题的样式，UTF-8解码后很正常，因为本身就是UTF-8编码的：</p><pre class="csharpcode"><span class="rem">/*新导航*/</span>
#new_nav ul{ width:672px; height:33px; margin:0px; padding:0px;  }</pre><p>当使用gb2312解码之后得到如下:</p><pre class="csharpcode">/*鏂板鑸?/
#new_nav ul{ width:672px; height:33px; margin:0px; padding:0px;}</pre><p>很明显的，下面的样式都被注释掉了。自然一切问题都得以解释了。</p><p>解决办法很多种，但目标都是一个，保证文档声明和实际字符集的一致。对于CSS样式表，我们可以在文件头显式设置@charset ‘XXX’来声明字符集。或者在使用link引用外部样式表的时候显式加上charset属性。</p><p>另外，如果所有文件都能保存为utf-8 with signature的话，也就是带BOM标记的UTF-8编码格式，那么所有浏览器都能自识别，而不会产生识别错误的问题。</p><h2>Asp.Net中涉及到的编码问题</h2><p>第二个问题虽然我知道还是编解码的环节出了问题，但还是分析了我半天才找到问题所在。</p><h3>测试环境简化</h3><p>为了简单，我把第二个问题中涉及到的页面简化成如下两个文件：</p><p>Default.aspx文件：</p><pre class="csharpcode"><span class="asp">&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeFile=&quot;Default.aspx.cs&quot; Inherits=&quot;_Default&quot; %&gt;</span>
<span class="kwrd">&lt;!</span><span class="html">DOCTYPE</span> <span class="attr">html</span> <span class="attr">PUBLIC</span> <span class="kwrd">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="kwrd">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span> <span class="attr">xmlns</span><span class="kwrd">=&quot;http://www.w3.org/1999/xhtml&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">p</span><span class="kwrd">&gt;</span><span class="asp">&lt;%</span>= Msg <span class="asp">%&gt;</span><span class="kwrd">&lt;/</span><span class="html">p</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">p</span><span class="kwrd">&gt;</span>
        Aspx页面中的中文
    <span class="kwrd">&lt;/</span><span class="html">p</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span></pre><p>Default.aspx.cs后台代码文件：</p><pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> _Default : System.Web.UI.Page
{
    <span class="kwrd">public</span> String Msg = <span class="str">&quot;代码中的中文&quot;</span>;
    <span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
    {
    }
}</pre><p>两个文件非常简单，从aspx文件中输出一段文字，从cs文件中输出一段文件。</p><h3>Asp.Net页面涉及到的编解码环节</h3><p>为了理解第二个问题，我们首先先来看一下在Asp.Net中一个页面究竟会涉及到什么编码环节。</p><p><font color="#800080">1. 文件本身存储使用的编码（在Visual Studio中新建文件的默认编码是UTF-8 With BOM）</font></p><p><font color="#800080">2. 文件被Asp.Net引擎转换处理时使用的编码</font></p><p><font color="#800000">3. 文件写到HTTP响应流时使用的编码</font></p><p><font color="#800000">4. 文件在HTTP头声明的编码（Content-Type=”text/html;charset=xxx”）</font></p><p>对于第一个环节就不需要说了，直接“Advanced Save As..”然后选择相应编码即可。对于2、3、4环节中涉及到的编码，asp.Net提供了全局配置还有页面级配置两种方式。</p><p>在web.config文件中可以管理全局编码配置。</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">configuration</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">system.web</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">globalization</span> <span class="attr">responseEncoding</span><span class="kwrd">=&quot;utf-8&quot;</span> <span class="attr">fileEncoding</span><span class="kwrd">=&quot;utf-8&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">system.web</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">configuration</span><span class="kwrd">&gt;</span></pre><p>在system.web一节下添加globalization元素，它有几个可配置选项，具体参见<a title="Configures the globalization settings for an application" href="http://msdn.microsoft.com/en-us/library/hy4kkhe0.aspx" target="_blank">MSDN</a>。其中有两个属性和此次的问题相关，一个是fileEncoding（注意区分大小写），这个配置项决定了asp.net引擎在将aspx文件以及cs文件合并成html文档时使用的编码。<strong><font color="#008000">如果aspx或者cs文件的格式和此属性配置的不一致，那么就有可能导致生成的html文档出现乱码</font></strong>。默认情况下，该属性的值为ANSI编码，也就是说中文系统下为GB2312。但是如果文档本身存储格式是UTF-8 with BOM，那么asp.net将始终以UTF-8编码来解析aspx和cs文件。这也是为什么默认情况下什么都不需要配置的缘故。</p><p>另外一个属性是responseEncoding，这个配置决定了上述的第3、4环节，也就是当asp.net生成好html文档之后，将其写入HTTP响应正文时使用的编码，同时会设置HTTP的Content-Type响应头中的charset域。如果前面的环节没有问题，html生成正常的话，那么这里无论设置什么编码浏览器均会正常解码，页面上都不会有乱码。但是如果前面的步骤出了问题，那自然就会有乱码产生了。</p><p>注意上面4个环节我分别用了两种颜色来标明，看了上面的解释之后你就很明白了，1和2环节编码需一致，否则中间生成的html文档就已经有乱码了。3和4环节的编码须一致，否则浏览器显示不正常。</p><p>客户网站出现的部分文字乱码问题的原因就是因为aspx文件存储的格式是不带BOM标记的UTF-8（天知道他是怎么给整成这个编码的）而CS文件没有改动过，还是UTF-8 with BOM，而全局的fileEncoding没有配置，因此在第二个环节的时候使用gb2312去解析一个utf-8的文档，自然有问题，因此aspx文件中的中文显示为乱码，而cs文件中指定的中文正常显示。</p><p>上面介绍的是asp.net中的全局编码配置，其实针对每个页面还可以进行特殊配置。例如在aspx页面中的Page指令中可以添加ResponseEncoding属性。</p><p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/11/image_thumb22.png" width="244" height="36" /></p><p>或者我们可以在后台C#代码中利用Response对象。</p><p>Response对象提供了两个和字符集编码相关的属性，Response.Charset和Response.ContentEncoding。这两个有什么区别呢？ContentEncoding和web.config中配置的responseEncoding是等价的，都是既影响HTTP响应流编码又影响Content-Type响应头，而Charset影响的只是响应头Content-Type而已。 将其设置为null的话，Content-Type中就不会有charset域了。</p><p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>标签：<a href="http://www.imkevinyang.com/tags/aspdotnet" title="AspDotNet" rel="tag">AspDotNet</a>, <a href="http://www.imkevinyang.com/tags/content-type" title="Content-Type" rel="tag">Content-Type</a>, <a href="http://www.imkevinyang.com/tags/http-watch" title="HTTP Watch" rel="tag">HTTP Watch</a>, <a href="http://www.imkevinyang.com/tags/response" title="Response" rel="tag">Response</a>, <a href="http://www.imkevinyang.com/tags/%e5%ad%97%e7%ac%a6%e9%9b%86" title="字符集" rel="tag">字符集</a>, <a href="http://www.imkevinyang.com/tags/%e6%a0%b7%e5%bc%8f%e8%a1%a8" title="样式表" rel="tag">样式表</a>, <a href="http://www.imkevinyang.com/categories/techarticles/knottyproblems" title="疑难杂症" rel="tag">疑难杂症</a>, <a href="http://www.imkevinyang.com/tags/%e7%bc%96%e8%a7%a3%e7%a0%81" title="编解码" rel="tag">编解码</a><br /><h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4><ul class="st-related-posts"><li><a href="http://www.imkevinyang.com/2009/04/excel%e4%b8%ad%e4%bd%bf%e7%94%a8vba%e8%87%aa%e5%ae%9a%e4%b9%89%e5%87%bd%e6%95%b0%e5%af%b9%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%bb%a7%e7%bb%adurl%e7%bc%96%e7%a0%81.html" title="Excel中使用VBA自定义函数对字符串进行Url编码（UTF-8） (2009/04/28)">Excel中使用VBA自定义函数对字符串进行Url编码（UTF-8）</a> (2009/04/28)</li><li><a href="http://www.imkevinyang.com/2010/02/silverlight%e5%90%af%e7%94%a8assembly-caching%e4%b9%8b%e5%90%8e%e9%93%81%e9%80%9a%e7%94%a8%e6%88%b7%e6%97%a0%e6%b3%95%e8%ae%bf%e9%97%ae.html" title="Silverlight启用Assembly Caching之后铁通用户无法访问 (2010/02/13)">Silverlight启用Assembly Caching之后铁通用户无法访问</a> (2010/02/13)</li><li><a href="http://www.imkevinyang.com/2009/11/%e3%80%90%e6%8e%a8%e8%8d%90%e3%80%91%e4%b8%a4%e6%ac%behttp%e6%b5%81%e9%87%8f%e5%88%86%e6%9e%90%e5%b7%a5%e5%85%b7%e7%9a%84%e6%af%94%e8%be%83.html" title="【推荐】两款HTTP流量分析工具的比较 (2009/11/08)">【推荐】两款HTTP流量分析工具的比较</a> (2009/11/08)</li><li><a href="http://www.imkevinyang.com/2009/02/%e5%ad%97%e7%ac%a6%e7%bc%96%e8%a7%a3%e7%a0%81%e7%9a%84%e6%95%85%e4%ba%8b%ef%bc%88ascii%ef%bc%8cansi%ef%bc%8cunicode%ef%bc%8cutf-8%e5%8c%ba%e5%88%ab%ef%bc%89.html" title="字符编解码的故事（ASCII，ANSI，Unicode，Utf-8区别） (2009/02/28)">字符编解码的故事（ASCII，ANSI，Unicode，Utf-8区别）</a> (2009/02/28)</li><li><a href="http://www.imkevinyang.com/2009/11/%e5%ad%97%e7%ac%a6%ef%bc%8c%e5%ad%97%e8%8a%82%e5%92%8c%e7%bc%96%e7%a0%81.html" title="字符，字节和编码 (2009/11/27)">字符，字节和编码</a> (2009/11/27)</li><li><a href="http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html" title="文档字符集导致的脚本错误 (2009/08/19)">文档字符集导致的脚本错误</a> (2009/08/19)</li><li><a href="http://www.imkevinyang.com/2009/09/%e8%a7%a3%e5%86%b3xaml%e4%b8%ad%e5%8c%85%e5%90%ab%e4%b8%ad%e6%96%87%e5%af%bc%e8%87%b4%e6%97%a0%e6%b3%95%e7%bc%96%e8%af%91%e7%9a%84%e9%97%ae%e9%a2%98.html" title="解决Xaml中包含中文导致无法编译的问题 (2009/09/29)">解决Xaml中包含中文导致无法编译的问题</a> (2009/09/29)</li><li><a href="http://www.imkevinyang.com/2009/08/%e8%af%a6%e8%a7%a3javascript%e4%b8%ad%e7%9a%84url%e7%bc%96%e8%a7%a3%e7%a0%81.html" title="详解Javascript中的Url编码/解码 (2009/08/19)">详解Javascript中的Url编码/解码</a> (2009/08/19)</li><li><a href="http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html" title="（转）Http 请求处理流程 (2009/07/20)">（转）Http 请求处理流程</a> (2009/07/20)</li></ul>]]></content:encoded> <wfw:commentRss>http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>（转）Http 请求处理流程</title><link>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html</link> <comments>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html#comments</comments> <pubDate>Mon, 20 Jul 2009 15:24:00 +0000</pubDate> <dc:creator>Kevin Yang</dc:creator> <category><![CDATA[好文分享]]></category> <category><![CDATA[AspDotNet]]></category> <category><![CDATA[HTTP请求]]></category> <category><![CDATA[原理]]></category> <category><![CDATA[应用程序域]]></category><guid isPermaLink="false">http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html</guid> <description><![CDATA[<p class="quote"><font color="#ff8040">文章来自：</font><a href="http://www.tracefact.net/Asp-Net-Architecture/Http-Request-Processing-Flow.aspx" target="_blank">张子阳</a></p><h2>引言</h2><p>我查阅过不少Asp.Net的书籍，发现大多数作者都是站在一个比较高的层次上讲解Asp.Net。他们耐心、细致地告诉你如何一步步拖放控件、设置控件属性、编写CodeBehind代码，以实现某个特定的功能。</p><p>这种做法，实际上是回答了<strong>&#34;如何去做&#34;</strong>的问题，却没有回答<strong>&#34;为什么可以这样做&#34;</strong>的问题。</p><p>尽管我很推崇 悉江华 先生的《圣殿祭祀的Asp.Net开发详解》一书，但当我翻看了一下其对角色(Ro&#8230;</p>]]></description> <content:encoded><![CDATA[</p><p class="quote"><font color="#ff8040">文章来自：</font><a href="http://www.tracefact.net/Asp-Net-Architecture/Http-Request-Processing-Flow.aspx" target="_blank">张子阳</a></p><h2>引言</h2><p>我查阅过不少Asp.Net的书籍，发现大多数作者都是站在一个比较高的层次上讲解Asp.Net。他们耐心、细致地告诉你如何一步步拖放控件、设置控件属性、编写CodeBehind代码，以实现某个特定的功能。</p><p>这种做法，实际上是回答了<strong>&quot;如何去做&quot;</strong>的问题，却没有回答<strong>&quot;为什么可以这样做&quot;</strong>的问题。</p><p>尽管我很推崇 悉江华 先生的《圣殿祭祀的Asp.Net开发详解》一书，但当我翻看了一下其对角色(Role) 和 用户(Member)的讲解时，我决定跳过去直接读后面的章节。因为我发现他也随了大流，对这部分的讲解停留在&quot;如何去做&quot;的层面上。我相信像悉先生 这样的牛人是不可能不了解底层运作原理的，仅仅是因为那本书原本就已经很厚了吧。</p><p>当你按&quot;如何去做&quot;所讲解的内容去开发程序的时候，对于你的用户，你仍是一名程序员；但对于实现了MembershipProvider 和 RoleProvider 抽象类的微软开发人员来说，你已经成了他们的一个用户。</p><p><strong>NOTE：</strong>我既不反对一些作者只讲解&quot;如何去做&quot;，也不反对你只学&quot;如何去做&quot;，这样也有它的好处，就是可以快速开发。我只是建议多掌握一点底层知识，对一些问题会有更好的理解。</p><p>希望通过这一系列文章的讲解，可以让你更好的理解Asp.Net的运作原理和做以了解。</p><h2>Http请求处理流程概述</h2><p>思考&quot;为什么在地址栏输入www.tracefact.net就可以看到张子阳的个人空间？&quot;，类似于思考&quot;为什么苹果是往地上掉不是往天上 飘？&quot;。对于普通访问者来说，这就像每天太阳东边升起西边落下一样是理所当然的；对于很多程序员来说，认为这个与己无关，不过是系统管理员或者网管员的责 任。毕竟，IIS是 Windows 的一个组件，又不是 Asp.Net 的一个组成部分。而实际上，从你轻拍回车到页面呈现在你眼前的十分之一秒内，IIS和.Net Framework已经做了大量的幕后工作。</p><p>你可能觉得了解这些幕后工作是如何运作的无关紧要，作为程序员的你只要保证开发出的程序可以高效地运行就可以了。然而，在开发过程中，你却发现常常 需要使用诸如 HttpContext 这样的类。这个时候，你可曾思考过这些类的构成和类的实体是如何创建的？你可能简单地回答：HttpContext代表当前请求的一个上下文环境。可你又 知道IIS 、Framework、Asp.Net 是如何协同工作处理每个Http请求、如何区分不同的请求、IIS、Framework、Asp.Net三者之间的数据如何流动么？</p><p>回答上面这些问题，首先需要了解IIS是如何处理页面请求的，这也是理解 Form验证模式和Windows 验证模式 的基础。</p><h2>Http请求刚刚到达服务器的时候</h2><p>当服务器接收到一个 Http请求的时候，IIS 首先需要决定如何去处理这个请求（<strong>NOTE：</strong>服务器处理一个.htm页面和一个.aspx页面肯定是不一样的么）。那IIS依据什么去处理呢？―― 根据文件的后缀名。</p><p>服务器获取所请求的页面（<strong>NOTE：</strong>也可以是文件，比如 jimmy.jpg）的后缀名以后，接下来会在服务器端寻找可以处理这类后缀名的应用程序，如果IIS找不到可以处理此类文件的应用程序，并且这个文件也没有受到服务器端的保护（<strong>NOTE：</strong>一个受保护的例子就是 App_Code中的文件，一个不受保护的例子就是你的js脚本），那么IIS将直接把这个文件返还给客户端。</p><p>能够处理各种后缀名的应用程序，通常被称为 ISAPI 应用程序（<strong>NOTE：</strong>Internet Server Application Programe Interface，互联网服务器应用程序接口）。虽然这 ISAPI 听上去还挺气派，也算是&quot;应用程序&quot;呢，但仔细看看它的全称就明白了：<strong></strong><strong><font color="#008000"><strong>它实际上只是一个接口，起到一个代理的作用，它的主要工作是映射所请求的页面(文件) 和与此后缀名相对应的实际的处理程序。</strong></font></strong></p><p>让我们更进一步地看一下 ISAPI ，看看它到底是什么样子，请按下面的步骤进行：</p><ol><li>打开IIS。</li><li>选择随意一个站点，鼠标右键，&quot;属性&quot;。</li><li>选择&quot;主目录&quot;选项卡。</li><li>选择&quot;配置&quot;。</li></ol><p>你应该会看到如下的画面：</p><p>图1. 应用程序配置</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image001.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="应用程序配置" border="0" alt="应用程序配置" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image001_thumb.gif" width="465" height="515" /></a></p><p>很清楚地就可以看到，所有IIS所能处理，或者叫 ISAPI 所提供代理服务的 文件类型 及其相对应的实际的后台处理程序都在这里清楚地列出来了。</p><p>我们找到 .aspx 的应用处理程序，然后点&quot;编辑&quot;，会出现下面的画面：</p><p>图2. 编辑.aspx文件的处理程序</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image002.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="编辑.aspx文件的处理程序" border="0" alt="编辑.aspx文件的处理程序" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image002_thumb.gif" width="515" height="295" /></a></p><p>一路看到这里，可以看出，所有的.aspx文件实际上都是由 aspnet_isapi.dll 这个程序来处理的，当IIS把对于.aspx页面的请求提交给了aspnet_isapi.dll以后，它就不再关心这个请求随后是如何处理的了。现在我们应该知道：Asp.Net 只是服务器(IIS)的一个组成部分而已，它是一个 ISAPI扩展。</p><p>这里需要注意两点：</p><ul><li>当你修改&quot;限制为&quot;后，可以限制页面(文件)只能以某种特定方式访问</li><li>&quot;确认文件是否存在&quot;是实现 URL 地址映射的关键选项，我以后会专门讲述。</li></ul><h2>理解宿主环境（Hosting）</h2><p>从本质上讲，Asp.Net 主要是由一系列的类组成，这些类的主要目的就是将Http请求转变为对客户端的响应。HttpRuntime类是Asp.Net的一个主要入口，它有一个称作ProcessRequest 的方法，这个方法以一个 HttpWorkerRequest 类作为参数。HttpRuntime 类几乎包含着关于单个Http请求的所有信息：所请求的文件、服务器端变量、QueryString、Http 头信息 等等。Asp.Net 使用这些信息来加载、运行正确的文件，并且将这个请求转换到输出流中，一般来说，也就是HTML页面。</p><p><strong>NOTE：</strong>二般来说，也可以是张图片。</p><p>当 Web.config文件的内容发生改变 或者 .aspx文件发生变动的时候，为了能够卸载运行在同一个进程中的应用程序（<strong>NOTE：</strong>卸载也是为了重新加载），Http请求被分放在相互隔离的应用程序域中。</p><p><strong>NOTE：</strong>可能你以前就听过应用程序域，但是不了解怎么回事，应用程序域就是 AppDomain。</p><p>对于IIS来说，它依赖一个叫做 HTTP.SYS 的内置驱动程序来监听来自外部的 HTTP请求。在操作系统启动的时候，IIS首先在HTTP.SYS中注册自己的虚拟路径。</p><p><strong>NOTE：</strong>实际上相当于告诉HTTP.SYS哪些URL是可以访问的，哪些是不可以访问的。举个简单的例子：为什么你访问不存在的文件会出现 404 错误呢？就是在这一步确定的。</p><p>如果请求的是一个可访问的URL，HTTP.SYS会将这个请求交给 IIS 工作者进程。</p><p><strong>NOTE：</strong>IIS6.0中叫做 w3wp.exe，IIS5.0中叫做 aspnet_wp.exe。</p><p>每个工作者进程都有一个身份标识 以及 一系列的可选性能参数。</p><p><strong>NOTE：</strong>可选性能参数，是指诸如 回收机制的设置、超时时间设置 等等。</p><p><strong>接下来进行的事情就是上一章节讲述的 ISAPI 了。</strong></p><p><strong>NOTE：</strong>这部分的内容相关性比较强，为了让大家好理解，我最后还是决定把 ISAPI 放到前面了，可能全系列完成的时候会再调整吧。</p><p>除了映射文件与其对应的处理程序以外，ISAPI 还需要做一些其他的工作：</p><ol><li>从HTTP.SYS中获取当前的Httq请求信息，并且将这些信息保存到 HttpWorkerRequest 类中。</li><li>在相互隔离的应用程序域AppDomain中加载HttpRuntime。</li><li>调用 HttpRuntime的ProcessRequest方法。</li></ol><p>接下来才是程序员通常编写的代码所完成的工作了，然后，IIS 接收返回的数据流，并重新返还给 HTTP.SYS，最后，HTTP.SYS 再将这些数据返回给客户端浏览器。</p><p>OK，现在你看到张子阳的空间主页了。</p><p>图3.Asp.Net 的宿主环境</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image0018.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Asp.Net 的宿主环境" border="0" alt="Asp.Net 的宿主环境" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image0018_thumb.gif" width="465" height="352" /></a></p><h2>理解管道（Pipeline）</h2><p>在前面两章中，我们在一个相对比较低的层次上讨论了从发出Http请求到看到浏览器输出这转瞬即逝的十分之一秒内IIS和 Framework 所做的事情。但是我们忽略了一个细节：程序员编写的代码是如何在这一过程中衔接的，本章我们就来看看这个问题。</p><p>当Http请求进入 Asp.Net Runtime以后，它的管道由托管模块（NOTE：Managed Modules）和处理程序（NOTE：Handlers）组成，并且由管道来处理这个 Http请求。<a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image00110.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="来自宿主环境的HTTP请求" border="0" alt="来自宿主环境的HTTP请求" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image00110_thumb.gif" width="515" height="373" /></a></p><p>我们按编号来看一下这幅图中的数据是如何流动的。</p><p>1. HttpRuntime将Http请求转交给 HttpApplication，HttpApplication代表着程序员创建的Web应用程序。HttpApplication创建针对此Http 请求的 HttpContext对象，这些对象包含了关于此请求的诸多其他对象，主要是HttpRequest、HttpResponse、 HttpSessionState等。这些对象在程序中可以通过Page类或者Context类进行访问。、</p><p>2. 接下来Http请求通过一系列Module，这些Module对Http请求具有完全的控制权。<strong></strong><strong><font color="#008000"><strong>这些Module可以做一些执行某个实际工作前的事情</strong>。</font></strong></p><p>3. Http请求经过所有的Module之后，它会被HttpHandler处理。在这一步，执行实际的一些操作，通常也就是.aspx页面所完成的业务逻 辑。可能你会觉得在创建.aspx页面并没有体会到这一过程，但是，你一定知道，.aspx 页面继承自Page类，我们看一下Page类的签名：</p><p>public class Page : TemplateControl, IHttpHandler{ <br />// 代码省略 <br />}</p><p>可以看到，Page类实现了IHttpHandler接口，HttpHandler也是Http请求处理的最底层。</p><p>4.HttpHandler处理完以后，Http请求再一次回到Module，<strong>此时Module可以做一些某个工作已经完成了之后的事情。</strong></p><p><strong>NOTE：</strong>注意我用红色标识的字，然后回想一下：Asp.Net 中是不是有众多的 Inserting 、Inserted 之类成对的事件？其实，这里讲述的就是为什么Asp.Net可以将一个Insert操作分成前后两部分，然后再分别进行事件拦截的幕后原理。</p><p>如果我们将注意力只集中在Http请求、HttpHandler和HttpModule上，不去考虑HttpContext和HttpApplication，那么图4.可以简化成下面这样：</p><p><strong>图5.Http请求在HttpHandler 和 HttpModule 中的流动方向</strong></p><p><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Http请求在HttpHandler 和 HttpModule 中的流动方向" border="0" alt="Http请求在HttpHandler 和 HttpModule 中的流动方向" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/image_thumb.png" width="219" height="296" /></p><h2>总结</h2><p>本文中，我首先概要介绍了这系列文章将要为大家讲述的主题。然后，我提出了部分程序员存在的一个问题：在一个比较高的层次上学习和使用Asp.Net。</p><p>随后，我以一个访问我个人空间首页的例子，引出了本文主要讲述的三个内容：</p><ol><li>Http请求刚刚到达时IIS时，IIS 所做的工作。</li><li>Http请求的宿主环境。</li><li>Http管道。</li></ol><p>希望这篇文章能给你带来帮助。</p>标签：<a href="http://www.imkevinyang.com/tags/aspdotnet" title="AspDotNet" rel="tag">AspDotNet</a>, <a href="http://www.imkevinyang.com/tags/http%e8%af%b7%e6%b1%82" title="HTTP请求" rel="tag">HTTP请求</a>, <a href="http://www.imkevinyang.com/tags/%e5%8e%9f%e7%90%86" title="原理" rel="tag">原理</a>, <a href="http://www.imkevinyang.com/categories/greatpoststoshare" title="好文分享" rel="tag">好文分享</a>, <a href="http://www.imkevinyang.com/tags/%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9f%9f" title="应用程序域" rel="tag">应用程序域</a><br /><h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4><ul class="st-related-posts"><li><a href="http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html" title="Asp.Net页面的编码问题 (2009/11/27)">Asp.Net页面的编码问题</a> (2009/11/27)</li></ul>]]></content:encoded> <wfw:commentRss>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>