Asp.net WebPages架構運行原理淺析(轉)

來源:互聯網
上載者:User

標籤:

在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 WebPages架構運行原理淺析(轉)

相關關鍵詞:
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.