標籤:state 分享 reg 更改 code sem token web程式 tty
建立第一個MVC程式
我們先建立一個ASP.NET Web程式
模板選擇MVC,因為不想使用預設的身份認證我們點擊更改身份認證並選擇不進行身份認證。
建立的項目結構如下:
配置與初始化Web設定檔
查看項目的web.config文,首先是appSettings
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
先是設定webpages架構的版本webpages:Version,然後是設定webpages:Enabled防止webpages頁面(cshtml )的直接執行。
ClientValidationEnabled和UnobtrusiveJavaScriptEnabled主要用於各htmlhelper方法,控制產生的用戶端html代碼,其中ClientValidationEnabled是指是否開啟用戶端驗證,UnobtrusiveJavaScriptEnabled是指是否開啟非侵入式JavaScript驗證(通過給html元素添加元屬性實現驗證),這裡不做過多深入。
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
System.web的設定目前很簡單,只是設定了debug和.net版本。
再下面是封裝每個程式集的繫結原則和程式集位置,每個程式集使一個dependentAssembly 元素。最後是指定可用語言提供者的編譯器配置設定。
此外還有預設產生的兩個設定檔分別是用於Debug和Release模式的,根據配置的不同將對應的設定檔添加到最終產生的web.config中。
註冊地區
再來查看預設產生的Global.asax檔案,我們知道在第一次請求的時候該檔案就已經被編譯並會調用其中定義的Application_Start方法。
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }
首先是註冊所有的地區,其實現在AreaRegistration類中(在System.Web.Mvc下實現)。
public static void RegisterAllAreas() { RegisterAllAreas(null); } public static void RegisterAllAreas(object state) { RegisterAllAreas(RouteTable.Routes, new BuildManagerWrapper(), state); } internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state) { List<Type> areaRegistrationTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsAreaRegistrationType, buildManager); foreach (Type areaRegistrationType in areaRegistrationTypes) { AreaRegistration registration = (AreaRegistration)Activator.CreateInstance(areaRegistrationType); registration.CreateContextAndRegister(routes, state); } }
其中TypeCacheUtil.GetFilteredTypesFromAssemblies會掃描所有相關程式集(BuildManager.GetReferencedAssemblies)擷取實現了AreaRegistration的類(而且必須有可訪問的無參的建構函式)。然後建立執行個體並調用CreateContextAndRegister註冊地區。
internal void CreateContextAndRegister(RouteCollection routes, object state) { AreaRegistrationContext context = new AreaRegistrationContext(AreaName, routes, state); string thisNamespace = GetType().Namespace; if (thisNamespace != null) { context.Namespaces.Add(thisNamespace + ".*"); } RegisterArea(context); }
其中具體的註冊方法RegisterArea是一個虛方法,我們建立一個地區看看它是如何?的,在MVC程式中通過右鍵建立一個名為Teacher的地區,自動產生的AreaRegistration代碼如下:
public class TeacherAreaRegistration : AreaRegistration { public override string AreaName { get { return "Teacher"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "Teacher_default", "Teacher/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } ); } }
可以看到最終是通過AreaRegistrationContext的MapRoute向RouteTable註冊了路由。
public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) { if (namespaces == null && Namespaces != null) { namespaces = Namespaces.ToArray(); } Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces); route.DataTokens[RouteDataTokenKeys.Area] = AreaName; bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0); route.DataTokens[RouteDataTokenKeys.UseNamespaceFallback] = useNamespaceFallback; return route; }
可以知道AreaName被註冊到了route.DataTokens[RouteDataTokenKeys.Area]中。
過濾器、路由和資源
接下來看Global.asax的下面三行代碼:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles);
這是我們比較熟悉的註冊全域過濾器、註冊路由和註冊綁定(主要是css和js資源)了。其實際工作有一下三個類完成。對於過濾器和路由的機制留到以後再詳細分析,這裡簡單介紹一下資源綁定。
查看具體的代碼
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( "~/Scripts/bootstrap.js", "~/Scripts/respond.js")); bundles.Add(new StyleBundle("~/Content/css").Include( "~/Content/bootstrap.css", "~/Content/site.css"));
我們可以看到兩種綁定ScriptBundle(js指令碼)和StyleBundle(css),值得注意的是StyleBundle方法的參數virtualPath需要根據綁定的css來設定(設定成css檔案同目錄,避免css中的一些相對路徑失效),如果js指令碼中有引用其他指令碼也是一樣。頁面使用時直接通過Scripts或Styles的靜態方法Render(paths)在頁面中引用資源。
Asp.Net MVC-01-起步