ASP.NET的运行原理与运行机制
在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebForms这种模仿Windows Form编程方式有了很大不同,不再有大量控件和控件生成的大量不够灵活的代码,但是同样可以使用Asp.net提供的大量类库和功能,可以说WebPages框架融合了Asp、PHP和Asp.net的全部优点,又可使用C#和VB编程语言。一看到WebPages框架,我就马上有了深入学习的兴趣,因为它和WebForms相比立刻就会让有完美主义情结的程序员们倾心。
但WebPages框架却并没有绑定Razor语法,它可以使用第三方的视图引擎。WebPages和Razor也并没有和Asp.net MVC具有必然的联系。在VS2012中默认的网站模板里面多了”Asp.net网站(Razor v2)“,可以根据Razor语法创建WebPage。
WebPages网站简介
WebPages网站包含多个cshtml或vbhtml页面,这些页面中使用Razor模板语法,整个网站的文件都在一个文件夹中,bin目录中有各种要用到的dll,没有解决方案文件,解决方案文件在另外一个和网站同时创建的项目中,其中有packages目录以管理WebPages网站需要用到的包。一个普通的cshtml页代码如下:
@{
var db = Database.Open("StarterSite");
var users = db.Query("Select * From UserProfile");
var grid = new WebGrid(users);
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
@grid.GetHtml()
</body>
</html>
从中可以看到,这种编写方式和PHP、Asp很相似,但WebPages身后却是庞大的Asp.net类库。
WebPages框架相关配置
在WebPages网站的web.config中并没有什么特殊配置,在.net framework 4.0中的web.config中相关的配置如下:
<compilation>
<assemblies>
<remove assembly="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add assembly="System.Web.WebPages.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblies>
</compilation> <httpHandlers>
<add path="*.cshtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.cshtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
<add path="*.vbhtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
</httpHandlers>
其中没有相关buildProviders的配置也没有相关httpModules的配置,httpHandlers的配置还将其映射到了HttpForbiddenHandler禁止访问。在IIS或IIS Express中的配置中也只有Asp.net4.0的ISAPI的配置而没有相关的httpModule。而WebForms在web.config中配置有相应的httpHandler和buildProvider。那么WebPages框架是如何运行的,其和WebForms在哪里产生了不同,WebPages框架是如何在Asp.net框架下实现的,这就需要进入WebPages框架进行探索。
WebPages框架自动运行过程
从web.config中的System.Web.WebPages.Deployment程序集开始,这个程序集dll有一个Asp.net4.0新增的特性PreApplicationStartMethodAttribute,这个特性配置了一个静态方法以在程序启动之前自动执行,特性如下:[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")],查看PreApplicationStartCode类的Start方法,其调用了StartCore方法,StartCore又调用了LoadWebPages方法,其中实现的功能主要是获取所有和WebPages框架相关的dll并得到这些dll上配置的PreApplicationStartMethodAttribute特性对应的启动方法并全部执行,具有这个特性的dll有System.Web.WebPages、System.Web.WebPages.Razor和WebMatrix.WebData,我们主要关注前两个。
private static void LoadWebPages(Version version)
{
IEnumerable<Assembly> assemblies = Enumerable.Select<AssemblyName, Assembly>(AssemblyUtils.GetAssembliesForVersion(version),
new Func<AssemblyName, Assembly>(null, (IntPtr) LoadAssembly)); foreach (Assembly assembly in assemblies)
{
BuildManager.AddReferencedAssembly(assembly);
}
foreach (MethodInfo info in GetPreStartInitMethodsFromAssemblyCollection(assemblies))
{
info.Invoke(null, null);
}
}
在System.Web.WebPages.Razor程序集上的启动方法代码如下:
public static class PreApplicationStartCode
{
// Fields
private static bool _startWasCalled;
// Methods
public static void Start()
{
if (!_startWasCalled)
{
_startWasCalled = true;
BuildProvider.RegisterBuildProvider(".cshtml", typeof(RazorBuildProvider));
BuildProvider.RegisterBuildProvider(".vbhtml", typeof(RazorBuildProvider));
}
}
}
其注册了cshtml和vbhtml文件对应的BuildProvider为RazorBuildProvider,即编译Razor语法文件的提供程序。
在System.Web.WebPages程序集上的启动方法代码如下,这些启动类的名字和方法是一样的
public static class PreApplicationStartCode
{
// Fields
private static bool _startWasCalled;
// Methods
public static void Start()
{
if (!_startWasCalled)
{
_startWasCalled = true;
WebPageHttpHandler.RegisterExtension("cshtml");
WebPageHttpHandler.RegisterExtension("vbhtml");
PageParser.EnableLongStringsAsResources = false;
//此行代码注册了WebPageHttpModule DynamicModuleUtility.RegisterModule(typeof(WebPageHttpModule)); ScopeStorage.CurrentProvider = new AspNetRequestScopeStorageProvider();
}
}
}
其中最重要的功能就是自动注册了一个HttpModule,到此我们就可以知道WebPages页面的编译和处理已经有了着落了。接着查看WebPageHttpModule的代码,这个httpmodule注册处理了HttpApplication的PostResolveRequestCache,BeginRequest和EndRequest事件,这些代码会在用户请求cshtml和vbhtml页面时触发执行,在这个过程中WebPageHttpModule还会在WebPages网站首次启动的时候调用System.Web.WebPages.ApplicationStartPage.ExecuteStartPage方法,在PostResolveRequestCache事件处理代码中调用了WebPageRoute的方法,其中创建了处理页面的WebPageHttpHandler类。
internal static void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
new WebPageRoute().DoPostResolveRequestCache(context);
}
internal void DoPostResolveRequestCache(HttpContextBase context)
{
if (!this.IsExplicitlyDisabled)
{
string pathValue = context.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + context.Request.PathInfo;
ReadOnlyCollection<string> registeredExtensions = WebPageHttpHandler.GetRegisteredExtensions();
WebPageMatch match = MatchRequest(pathValue, registeredExtensions, this.VirtualPathFactory, context, DisplayModeProvider.Instance);
if (match != null)
{
context.Items[typeof(WebPageMatch)] = match;
string path = "~/" + match.MatchedPath; //是否在WebPages网站的web.config中明确配置了webpages:Enabled
if (!WebPagesDeployment.IsExplicitlyDisabled(path))
{
//创建WebPageHttpHandler
IHttpHandler handler = WebPageHttpHandler.CreateFromVirtualPath(path);
if (handler != null)
{
SessionStateUtil.SetUpSessionState(context, handler); //替换web.config中配置的HttpForbiddenHandler
context.RemapHandler(handler);
}
}
}
else
{
string extension = PathUtil.GetExtension(pathValue);
foreach (string str4 in registeredExtensions)
{
if (string.Equals("." + str4, extension, StringComparison.OrdinalIgnoreCase))
{
throw new HttpException(0x194, null);
}
}
}
}
}
WebPageRoute还实现了WebPages网站页面地址更加友好的功能,如不必带cshtml和vbhtml后缀即可访问相应页面,可采用filename/category/id之类的地址访问,通过添加xx.Mobile.cshtml即可自动实现切换到移动页的功能等。到此HttpHandler创建完毕之后,就开始执行页面,WebPages页面的基类是System.Web.WebPages.WebPage。
如果我们在WebPages网站的web.config里面配置了webpages:Enabled为false,那么再次访问cshtml或vbhtml时发现处理它们的是HttpForbiddenHandler。
<appSettings>
<add key="webpages:Enabled" value="false"/>
</appSettings> 无法提供此类型的页
至此,我们对WebPages框架的相关运行原理有了一个大概的了解。WebPages框架通过Asp.net4.0提供的PreApplicationStartMethodAttribute特性实现了HttpModule和BuildProvider注册,而不是通常的web.config配置文件,本文介绍的过程并不是绝对的,因为这个特性是可以被Asp.net Runtime自动识别和运行的,例如只要你引用了System.Web.WebPages就会执行其上配置的注册WebPageHttpModule的方法,其这些程序集上的启动方法都有判断机制防止重复执行。
和Asp.net MVC中的Razor视图引擎的关系
Razor并没有和MVC紧密耦合,其可以脱离MVC,也可以脱离WebPage框架。System.Web.MVC程序集上也有PreApplicationStartMethodAttribute特性,其中分别直接调用了System.Web.WebPages和System.Web.WebPages.Razor中的启动类以注册WebPageHttpModule和RazorBuildProvider,但MVC之中又继承了System.Web.Razor中的WebPageRazorHost类实现了自己特有的MvcWebPageRazorHost,相当于增加了新的功能以和MVC配合。
正如MVC中有多种不同的视图引擎一样,WebPages框架也不一定要使用Razor引擎,我们可以实现自己的BuildProvider来定义WebPage语法和解析生成.Net程序集。
结语
个人认为WebPages框架在人们越来越注重Web标准和前端UI的情况下,抛弃了WebForms有些笨重和不透明的编程方式,具有极大的灵活性同时又可以利用Asp.net强大的类库,后端的框架模型并没有变,但却让Asp.net程序员有了和PHP、Asp类似的快速编程体验。受够了WebForms输出代码的臃肿的程序员们,赶快学习WebPages吧:)
ASP.NET的运行原理与运行机制的更多相关文章
- ASP.NET的运行原理与运行机制 如何:为 IIS 7.0 配置 <system.webServer> 节
https://technet.microsoft.com/zh-cn/sysinternals/bb763179.aspx 当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的 ...
- Struts2的运行原理和运行与原理
Struts2 struts2的流程图 运行机制 1.客户端发送请求.通过ActionContextLoader调用FilterDispatcher(struts) 2.FilterDispatche ...
- jsp运行原理及运行过程
JSP的执行过程主要可以分为以下几点: 1)客户端发出请求. 2)Web容器将JSP转译成Servlet源代码. 3)Web容器将产生的源代码进行编译. 4)Web容器加载编译后的代码并执行. 5)把 ...
- iBatis.Net的基本情况和运行原理
转载http://www.cnblogs.com/13590/archive/2013/02/27/2934580.html 摘要:介绍iBatis.Net的基本情况和运行原理,运行环境中各参数的配置 ...
- Babel运行原理
前言 之前翻博客园的时候,看到有人朋友分享阿里巴巴的面试题,其中有一道题就是关于ES6转ES5 原理的,当时我看到感觉到自己离去阿里巴巴的路还很远啊,像我们大部分做开发的时候,都只知其然不知 ...
- php 第1讲 html介绍 html运行原理①
1. html (hypertext mark-up language )是 超文本编辑语言,主要的用处是做网页,可以在网页上显示文字.图形.动画.视频... “标记“有时候也称之为“元素” 动态网页 ...
- asp.net运行原理及机制
当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块.在ASP.NET 3.5中,这个模 ...
- .NET/ASP.NET MVC Controller 控制器(深入解析控制器运行原理)
阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...
- Asp.net WebPages框架运行原理浅析(转)
在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用 WebFo ...
随机推荐
- bootstrap学习笔记<十>(按钮组,导航)
1)按钮组.样式:class="btn-group" <div class="btn-group"> <button class=" ...
- 查看package编译时的错误信息及重新编译
开发时,一般都是使用PL/SQL工具进行开发,查看编译错误及重新编译都很简单,但是一般的生产环境是不允许连接外界工具的,只能在命令行中进行重新编译及查看,今天我就遇到了这个问题,现在总结如下: 1.获 ...
- c++中vector的学习
根据各种做题,发现数组并不是很适用于各种情况,当涉及到内存占用的时候,数组可能就没有vector的优势了,而vector,动态数组,比较适合某些情况. 接下来看看比较基本的vector用法: 1 #i ...
- Java后端开发
Java后端开发 名称 内容 基本框架 Spring.Mybatis Linux服务器 数据库优化 消息服务 rabbitMQ.activeMq rocketMq 缓存服务 memcached ...
- kafka常用操作命令
1.启动Kafka,其中">>/dev/null"表示将日志信息输出到"黑洞",其中"2>&1"表示将错误信息和前 ...
- hiho_1089_floyd最短路
题目 floyd算法求所有顶点之间的最短路,典型的模板题.唯一需要注意的是两个顶点之间可能有多条边直接相连,在初始化的时候,直接选择最小的长度作为两点间的距离即可. 实现 #include<io ...
- eclipse 新建 maven 项目 添加 spring hibernate 的配置文件 详情
主要配置文件 pom.xml 项目的maven 配置文件 管理项目所需 jar 依赖支持 web.xml 项目的总 配置文件 :添加 spring和hibernate 支持 applicationC ...
- 琐碎的总结 css jQuery js 等等。。。
jQuery outerWidth(true)支持ie7 不错不错css BFC a {display:inline-block} 有用,block不是很有效果 ...
- alpha发布(技术随笔)
昨天是班级里面每个小组要进行alpha演示,大家都很努力的去做自己的项目.我们nice!组没有演示自己的项目,只一点很惭愧,身为组员没有协助组长按时完成项目,这一点自己也感觉很抱歉,虽然每天感觉自己都 ...
- WPF:linq
/// <summary> /// 该药品是否存在发药信息 /// 存在返回true,否则返回false /// </summary> /// <param name=& ...