在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页代码如下:

  1. @{
  2. var db = Database.Open("StarterSite");
  3. var users = db.Query("Select * From UserProfile");
  4. var grid = new WebGrid(users);
  5. }
  6. <!DOCTYPE html>
  7. <html>
  8. <head>
  9. <title></title>
  10. </head>
  11. <body>
  12. @grid.GetHtml()
  13. </body>
  14. </html>

从中可以看到,这种编写方式和PHP、Asp很相似,但WebPages身后却是庞大的Asp.net类库。

WebPages框架相关配置

在WebPages网站的web.config中并没有什么特殊配置,在.net framework 4.0中的web.config中相关的配置如下:

  1. <compilation>
  2. <assemblies>
  3. <remove assembly="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  4. <add assembly="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  5.  
  6. <add assembly="System.Web.WebPages.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  7. </assemblies>
  8. </compilation>
  9.  
  10. <httpHandlers>
  11. <add path="*.cshtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
  12. <add path="*.cshtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
  13. <add path="*.vbhtm" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
  14. <add path="*.vbhtml" verb="*" type="System.Web.HttpForbiddenHandler" validate="True"/>
  15. </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,我们主要关注前两个。

  1. private static void LoadWebPages(Version version)
    {
      IEnumerable<Assembly> assemblies = Enumerable.Select<AssemblyName, Assembly>(AssemblyUtils.GetAssembliesForVersion(version),
        new Func<AssemblyName, Assembly>(null, (IntPtr) LoadAssembly));
  2.  
  3.   foreach (Assembly assembly in assemblies)
      {
    BuildManager.AddReferencedAssembly(assembly);
      }
      foreach (MethodInfo info in GetPreStartInitMethodsFromAssemblyCollection(assemblies))
      {
    info.Invoke(null, null);
      }
    }

在System.Web.WebPages.Razor程序集上的启动方法代码如下:

  1. public static class PreApplicationStartCode
  2. {
  3. // Fields
  4. private static bool _startWasCalled;
  5. // Methods
  6. public static void Start()
  7. {
  8. if (!_startWasCalled)
  9. {
  10. _startWasCalled = true;
  11. BuildProvider.RegisterBuildProvider(".cshtml", typeof(RazorBuildProvider));
  12. BuildProvider.RegisterBuildProvider(".vbhtml", typeof(RazorBuildProvider));
  13. }
  14. }
  15. }

其注册了cshtml和vbhtml文件对应的BuildProvider为RazorBuildProvider,即编译Razor语法文件的提供程序。

在System.Web.WebPages程序集上的启动方法代码如下,这些启动类的名字和方法是一样的

  1. public static class PreApplicationStartCode
  2. {
  3. // Fields
  4. private static bool _startWasCalled;
  5. // Methods
  6. public static void Start()
  7. {
  8. if (!_startWasCalled)
  9. {
  10. _startWasCalled = true;
  11. WebPageHttpHandler.RegisterExtension("cshtml");
  12. WebPageHttpHandler.RegisterExtension("vbhtml");
  13. PageParser.EnableLongStringsAsResources = false;
  14.         //此行代码注册了WebPageHttpModule
  15.  
  16.        DynamicModuleUtility.RegisterModule(typeof(WebPageHttpModule));
  17.  
  18. ScopeStorage.CurrentProvider = new AspNetRequestScopeStorageProvider();
  19. }
  20. }
  21. }

其中最重要的功能就是自动注册了一个HttpModule,到此我们就可以知道WebPages页面的编译和处理已经有了着落了。接着查看WebPageHttpModule的代码,这个httpmodule注册处理了HttpApplication的PostResolveRequestCache,BeginRequest和EndRequest事件,这些代码会在用户请求cshtml和vbhtml页面时触发执行,在这个过程中WebPageHttpModule还会在WebPages网站首次启动的时候调用System.Web.WebPages.ApplicationStartPage.ExecuteStartPage方法,在PostResolveRequestCache事件处理代码中调用了WebPageRoute的方法,其中创建了处理页面的WebPageHttpHandler类。

  1. internal static void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
  2. {
  3.     HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
  4.   new WebPageRoute().DoPostResolveRequestCache(context);
  5. }
  1. internal void DoPostResolveRequestCache(HttpContextBase context)
  2. {
  3. if (!this.IsExplicitlyDisabled)
  4. {
  5. string pathValue = context.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + context.Request.PathInfo;
  6. ReadOnlyCollection<string> registeredExtensions = WebPageHttpHandler.GetRegisteredExtensions();
  7. WebPageMatch match = MatchRequest(pathValue, registeredExtensions, this.VirtualPathFactory, context, DisplayModeProvider.Instance);
  8. if (match != null)
  9. {
  10. context.Items[typeof(WebPageMatch)] = match;
  11. string path = "~/" + match.MatchedPath;
  12.  
  13.         //是否在WebPages网站的web.config中明确配置了webpages:Enabled
  14. if (!WebPagesDeployment.IsExplicitlyDisabled(path))
  15. {
  16. //创建WebPageHttpHandler
  17. IHttpHandler handler = WebPageHttpHandler.CreateFromVirtualPath(path);
  18. if (handler != null)
  19. {
  20. SessionStateUtil.SetUpSessionState(context, handler);
  21.  
  22.             //替换web.config中配置的HttpForbiddenHandler
  23. context.RemapHandler(handler);
  24. }
  25. }
  26. }
  27. else
  28. {
  29. string extension = PathUtil.GetExtension(pathValue);
  30. foreach (string str4 in registeredExtensions)
  31. {
  32. if (string.Equals("." + str4, extension, StringComparison.OrdinalIgnoreCase))
  33. {
  34. throw new HttpException(0x194, null);
  35. }
  36. }
  37. }
  38. }
  39. }

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。

  1. <appSettings>
  2. <add key="webpages:Enabled" value="false"/>
  3. </appSettings>
  4.  
  5. 无法提供此类型的页

至此,我们对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 WebPages框架运行原理浅析(转)的更多相关文章

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

    [来源] 达内    [编辑] 达内   [时间]2012-09-14 在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和 ...

  2. 【ASP.NET Core】运行原理之启动WebHost

    ASP.NET Core运行原理之启动WebHost 本节将分析WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build ...

  3. 【ASP.NET Core】运行原理[3]:认证

    本节将分析Authentication 源代码参考.NET Core 2.0.0 HttpAbstractions Security 目录 认证 AddAuthentication IAuthenti ...

  4. 【ASP.NET Core】运行原理(4):授权

    本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理(1):创建WebHost [ASP.NET Core]运行原理(2):启动WebHost [ASP.NET Core ...

  5. 【ASP.NET Core】运行原理(2):启动WebHost

    本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...

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

    本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...

  7. .NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析

    一.概述 在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载.Web应用程序的入口点由InetMgr.exe创建并调用托管,初始化过程中触发HttpApplicat ...

  8. SpringMVC运行原理浅析

    SpringMVC是主流的J2EEWEB层框架,SpringMVC是Sping家族中一个重要的产品.下面给出SpringMVC的运行原理.springmvc和spring无需通过中间层进行整合,spr ...

  9. net框架运行原理

    核心是CLR(通用语言运行时), c#或者其它各种语言编译原理:将原代码通过相对的编译器(语法检查原代码分析)生成IL代码托管(IL也称托管代码),最后得到一个托管模块,一个或多个托管模块组成程序集( ...

随机推荐

  1. Java总结篇系列:Java多线程(三)

    本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题. 一.一个典型的Java线程安全例子 public class ThreadTest { public static void ma ...

  2. C# ~ 由 IDisposable 到 GC

    IDisposable 接口 1. 托管资源和非托管资源   ·  托管资源  a.  CLR 控制和管理的内存资源,如程序中在 Heap 上分配的对象.作用域内的变量等:  b.  GC 机制实现自 ...

  3. Android Volley框架的使用(1)

    在Android开发中,经常要通过HTTP请求访问网络.为了使通过HTTP请求访问网络的过程更加简单,2013年提出了新的HTTP通信框架--Volley.Volley使用起来非常简单,适用于网络访问 ...

  4. 阿里云centos6.5下搭建javaWeb运行环境

    一.主要方法 http://blog.csdn.net/hdfyq/article/details/38456981 上面文章的步骤至mysql安装完毕以及设置(记住 update user set ...

  5. 容器--EnumMap

    一.概述 EnumMap是一类特殊的Map, 其特殊之处在于KEY需要是枚举类型,由于枚举类型的特点是值的个数是固定的,所以,对于EnumMap来说,其所能存储的个数也就是固定的了.这种类型的Map相 ...

  6. OpenWRT学习笔记-1@WNDR3800

    很久以前买了一台二手wndr3800 放假了刷成op可以一耍.ar71xx,芯片还比较热门. 首先是刷机,准备使用OP CC 15.05 r46767,官方稳定版.把原装系统降级到1.0.0.16,就 ...

  7. 前端优秀作品展示,JavaScript 版水果忍者

    <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版的切水果游戏由百度 JS 小组开发,采用 vml + svg 绘图,使用了 Rapha ...

  8. html5的发展历程和由此引起的政治斗争

    2007年,乔布斯断言拒绝Flash并预言HTML5时代来临,IT行业就对HTML5产生了一股宗教热情.HTML5有着许多出众的特性,可以直接在网页上绘图.嵌入音视频.实现信息互动,可以跨越iOS.A ...

  9. CSS3绘制六边形

    因为很简单,所以先总结一下:使用CSS3绘制六边形主要使用伪类:before和:after在源元素之前和之后再绘制两个元素,并利用css3的边框样式,将这两个元素变成三角形放置在源元素的两端即可. ( ...

  10. SharePoint Server 2016 Update

    Today’s post was written by Seth Patton, senior director of product management for the SharePoint te ...