Asp.net WebPages框架运行原理浅析(转)

在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吧:)

时间: 2024-08-04 20:42:14

Asp.net WebPages框架运行原理浅析(转)的相关文章

Asp.net WebPages框架运行原理浅析

[来源] 达内    [编辑] 达内   [时间]2012-09-14 在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准 在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebForms这种模仿Windows Form编程方式有了很大不同,不再有大量控件和控件生成的

【ASP.NET Core】运行原理(1):创建WebHost

本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core]运行原理[3]:认证 本节将分析WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build();代码. 源代码参考.NET Core 2.0.0 WebHostBuilder WebHost Kestrel 问题概要 Hostin

dedeCMS,标准的MVC框架运行原理和缓存

1.织梦的工作原理: a.模板引擎: b.内核文件的载入.读取: 运行原理:url->配置文件->公共函数文件->处理逻辑->模板引擎->展示:(公共函数文件.处理逻辑和模板引擎就是织梦的核心) 2.标准的MVC框架运行流程:程序首先从单人口文件开始运行,然后依次载入内核文件(同时开始各种的初始化).配置.类和动作(在这之前已经载入了模板引擎),运行到业务层,业务层又会给类和动作,最后才展示出来. 3.关于缓存: a.缓存类型: 按缓存类型划分:内存缓存.文件缓存.数据库缓存

net框架运行原理

核心是CLR(通用语言运行时), c#或者其它各种语言编译原理:将原代码通过相对的编译器(语法检查原代码分析)生成IL代码托管(IL也称托管代码),最后得到一个托管模块,一个或多个托管模块组成程序集(assembly)交给CLR运行: 编译器需要为托管模块生成完整的元数据:元数据:是一个数据表集合,其中有描述托管模块中引用类型和成员的,还有一些描述他们中成员类型和定义的,元数据和代码一起被嵌入到EXE或者DLL中:因此编译器同时产生元数据和IL代码,并且将它们嵌入到生成的托管模块中: 元数据在.

ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行

ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framework的关系和.NET Core的构成体系从总体上介绍.NET Core,接下来计划用一个系列对ASP.NET Core的运行原理进行剖析. ASP.NET Core 是新一代的 ASP.NET,早期称为 ASP.NET vNext,并且在推出初期命名为ASP.NET 5,但随着 .NET Core

ASP.NET的运行原理与运行机制 -转

转自:原文  http://www.cnblogs.com/sntetwt/archive/2011/03/11/1980500.html 当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块.在ASP.NET 3.5中,这个模块叫做HttpHandler(HTTP处理程序组件),之所以.aspx文件可以被服务器处理,就是因为在服务器端有默认的HttpHandler专门处理.aspx文

学习ASP.NET MVC5框架揭秘笔记-ASP.NET MVC是如何运行的(一)

ASP.NET MVC是如何运行的 ASP.NET由于采用了管道式设计,所以具有很好的扩展性,整个ASP.NET MVC应用框架就是通过扩展ASP.NET实现的.通过上面对ASP.NET管道设计的介绍我们知道,ASP.NET 的扩展点主要体现在HttpModule和HttpHandler这两个核心组件之上,整个ASP.NET MVC框架就是通过自定义的HttpModule和HttpHandler建立起来的. 接下来我们通过自定义组件来模拟ASP.NET MVC的运行原理. 1.4.1建立在迷你版

ASP.NET的运行原理与运行机制

http://kb.cnblogs.com/page/75702/ 当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块.在ASP.NET 3.5中,这个模块叫做HttpHandler(HTTP处理程序组件),之所以.aspx文件可以被服务器处理,就是因为在服务器端有默认的HttpHandler专门处理.aspx文件.IIS在将这条请求发送给能够处理这个请求的模块之前,还需要经过一些H

asp.net运行原理及机制

当一个HTTP请求到服务器并被IIS接收到之后,IIS首先通过客户端请求的页面类型为其加载相应的.dll文件,然后在处理过程中将这条请求发送给能够处理这个请求的模块.在ASP.NET 3.5中,这个模块叫做HttpHandler(HTTP处理程序组件),之所以.aspx文件可以被服务器处理,就是因为在服务器端有默认的HttpHandler专门处理.aspx文件.IIS在将这条请求发送给能够处理这个请求的模块之前,还需要经过一些HttpModule的处理,这些都是系统默认的Modules(用于获取