亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Asp.net WebPages框架運(yùn)行原理淺析

Original 2017-01-11 14:32:25 578
abstract:在Asp.net4和4.5中,新增了WebPages Framework,編寫(xiě)頁(yè)面代碼使用了新的Razor語(yǔ)法,代碼更加的簡(jiǎn)潔和符合Web標(biāo)準(zhǔn),編寫(xiě)方式更接近于PHP和以前的Asp,和使用WebForms這種模仿Windows Form編程方式有了很大不同,不再有大量控件和控件生成的大量不夠靈活的代碼,但是同樣可以使用Asp.net提供的大量類庫(kù)和功能,可以說(shuō)WebPages框架融合了Asp、PH

在Asp.net4和4.5中,新增了WebPages Framework,編寫(xiě)頁(yè)面代碼使用了新的Razor語(yǔ)法,代碼更加的簡(jiǎn)潔和符合Web標(biāo)準(zhǔn),編寫(xiě)方式更接近于PHP和以前的Asp,和使用WebForms這種模仿Windows Form編程方式有了很大不同,不再有大量控件和控件生成的大量不夠靈活的代碼,但是同樣可以使用Asp.net提供的大量類庫(kù)和功能,可以說(shuō)WebPages框架融合了Asp、PHP和Asp.net的全部?jī)?yōu)點(diǎn),又可使用C#和VB編程語(yǔ)言。一看到WebPages框架,我就馬上有了深入學(xué)習(xí)的興趣,因?yàn)樗蚖ebForms相比立刻就會(huì)讓有完美主義情結(jié)的程序員們傾心。

但WebPages框架卻并沒(méi)有綁定Razor語(yǔ)法,它可以使用第三方的視圖引擎。WebPages和Razor也并沒(méi)有和Asp.net MVC具有必然的聯(lián)系。在VS2012中默認(rèn)的網(wǎng)站模板里面多了”Asp.net網(wǎng)站(Razor v2)“,可以根據(jù)Razor語(yǔ)法創(chuàng)建WebPage。

WebPages網(wǎng)站簡(jiǎn)介

WebPages網(wǎng)站包含多個(gè)cshtml或vbhtml頁(yè)面,這些頁(yè)面中使用Razor模板語(yǔ)法,整個(gè)網(wǎng)站的文件都在一個(gè)文件夾中,bin目錄中有各種要用到的dll,沒(méi)有解決方案文件,解決方案文件在另外一個(gè)和網(wǎng)站同時(shí)創(chuàng)建的項(xiàng)目中,其中有packages目錄以管理WebPages網(wǎng)站需要用到的包。一個(gè)普通的cshtml頁(yè)代碼如下:

@{     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>


從中可以看到,這種編寫(xiě)方式和PHP、Asp很相似,但WebPages身后卻是龐大的Asp.net類庫(kù)。

WebPages框架相關(guān)配置

在WebPages網(wǎng)站的web.config中并沒(méi)有什么特殊配置,在.net framework 4.0中的web.config中相關(guān)的配置如下:

<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>


其中沒(méi)有相關(guān)buildProviders的配置也沒(méi)有相關(guān)httpModules的配置,httpHandlers的配置還將其映射到了HttpForbiddenHandler禁止訪問(wèn)。在IIS或IIS Express中的配置中也只有Asp.net4.0的ISAPI的配置而沒(méi)有相關(guān)的httpModule。而WebForms在web.config中配置有相應(yīng)的httpHandler和buildProvider。那么WebPages框架是如何運(yùn)行的,其和WebForms在哪里產(chǎn)生了不同,WebPages框架是如何在Asp.net框架下實(shí)現(xiàn)的,這就需要進(jìn)入WebPages框架進(jìn)行探索。

WebPages框架自動(dòng)運(yùn)行過(guò)程

從web.config中的System.Web.WebPages.Deployment程序集開(kāi)始,這個(gè)程序集dll有一個(gè)Asp.net4.0新增的特性PreApplicationStartMethodAttribute,這個(gè)特性配置了一個(gè)靜態(tài)方法以在程序啟動(dòng)之前自動(dòng)執(zhí)行,特性如下:[assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")],查看PreApplicationStartCode類的Start方法,其調(diào)用了StartCore方法,StartCore又調(diào)用了LoadWebPages方法,其中實(shí)現(xiàn)的功能主要是獲取所有和WebPages框架相關(guān)的dll并得到這些dll上配置的PreApplicationStartMethodAttribute特性對(duì)應(yīng)的啟動(dòng)方法并全部執(zhí)行,具有這個(gè)特性的dll有System.Web.WebPages、System.Web.WebPages.Razor和WebMatrix.WebData,我們主要關(guān)注前兩個(gè)。

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程序集上的啟動(dòng)方法代碼如下:

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)); 
        }
    }
 }


其注冊(cè)了cshtml和vbhtml文件對(duì)應(yīng)的BuildProvider為RazorBuildProvider,即編譯Razor語(yǔ)法文件的提供程序。

在System.Web.WebPages程序集上的啟動(dòng)方法代碼如下,這些啟動(dòng)類的名字和方法是一樣的

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; 
         //此行代碼注冊(cè)了WebPageHttpModule                   DynamicModuleUtility.RegisterModule(typeof(WebPageHttpModule));
             ScopeStorage.CurrentProvider = new AspNetRequestScopeStorageProvider();
         }
     } 
}


其中最重要的功能就是自動(dòng)注冊(cè)了一個(gè)HttpModule,到此我們就可以知道WebPages頁(yè)面的編譯和處理已經(jīng)有了著落了。接著查看WebPageHttpModule的代碼,這個(gè)httpmodule注冊(cè)處理了HttpApplication的PostResolveRequestCache,BeginRequest和EndRequest事件,這些代碼會(huì)在用戶請(qǐng)求cshtml和vbhtml頁(yè)面時(shí)觸發(fā)執(zhí)行,在這個(gè)過(guò)程中WebPageHttpModule還會(huì)在WebPages網(wǎng)站首次啟動(dòng)的時(shí)候調(diào)用System.Web.WebPages.ApplicationStartPage.ExecuteStartPage方法,在PostResolveRequestCache事件處理代碼中調(diào)用了WebPageRoute的方法,其中創(chuàng)建了處理頁(yè)面的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網(wǎng)站的web.config中明確配置了webpages:Enabled 
           if (!WebPagesDeployment.IsExplicitlyDisabled(path))
            {                 //創(chuàng)建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還實(shí)現(xiàn)了WebPages網(wǎng)站頁(yè)面地址更加友好的功能,如不必帶cshtml和vbhtml后綴即可訪問(wèn)相應(yīng)頁(yè)面,可采用filename/category/id之類的地址訪問(wèn),通過(guò)添加xx.Mobile.cshtml即可自動(dòng)實(shí)現(xiàn)切換到移動(dòng)頁(yè)的功能等。到此HttpHandler創(chuàng)建完畢之后,就開(kāi)始執(zhí)行頁(yè)面,WebPages頁(yè)面的基類是System.Web.WebPages.WebPage。

如果我們?cè)赪ebPages網(wǎng)站的web.config里面配置了webpages:Enabled為false,那么再次訪問(wèn)cshtml或vbhtml時(shí)發(fā)現(xiàn)處理它們的是HttpForbiddenHandler。

<appSettings>    <add key="webpages:Enabled" value="false"/> </appSettings>

無(wú)法提供此類型的頁(yè)

至此,我們對(duì)WebPages框架的相關(guān)運(yùn)行原理有了一個(gè)大概的了解。WebPages框架通過(guò)Asp.net4.0提供的PreApplicationStartMethodAttribute特性實(shí)現(xiàn)了HttpModule和BuildProvider注冊(cè),而不是通常的web.config配置文件,本文介紹的過(guò)程并不是絕對(duì)的,因?yàn)檫@個(gè)特性是可以被Asp.net Runtime自動(dòng)識(shí)別和運(yùn)行的,例如只要你引用了System.Web.WebPages就會(huì)執(zhí)行其上配置的注冊(cè)WebPageHttpModule的方法,其這些程序集上的啟動(dòng)方法都有判斷機(jī)制防止重復(fù)執(zhí)行。

和Asp.net MVC中的Razor視圖引擎的關(guān)系

Razor并沒(méi)有和MVC緊密耦合,其可以脫離MVC,也可以脫離WebPage框架。System.Web.MVC程序集上也有PreApplicationStartMethodAttribute特性,其中分別直接調(diào)用了System.Web.WebPages和System.Web.WebPages.Razor中的啟動(dòng)類以注冊(cè)WebPageHttpModule和RazorBuildProvider,但MVC之中又繼承了System.Web.Razor中的WebPageRazorHost類實(shí)現(xiàn)了自己特有的MvcWebPageRazorHost,相當(dāng)于增加了新的功能以和MVC配合。

正如MVC中有多種不同的視圖引擎一樣,WebPages框架也不一定要使用Razor引擎,我們可以實(shí)現(xiàn)自己的BuildProvider來(lái)定義WebPage語(yǔ)法和解析生成.Net程序集。

結(jié)語(yǔ)

個(gè)人認(rèn)為WebPages框架在人們?cè)絹?lái)越注重Web標(biāo)準(zhǔn)和前端UI的情況下,拋棄了WebForms有些笨重和不透明的編程方式,具有極大的靈活性同時(shí)又可以利用Asp.net強(qiáng)大的類庫(kù),后端的框架模型并沒(méi)有變,但卻讓Asp.net程序員有了和PHP、Asp類似的快速編程體驗(yàn)。受夠了WebForms輸出代碼的臃腫的程序員們,趕快學(xué)習(xí)WebPages吧:)


Release Notes

Popular Entries