咱们先建立一个ASP.NET Web程序css
模板选择MVC,由于不想使用默认的身份认证咱们点击更改身份认证并选择不进行身份认证。html
建立的项目结构以下:web
查看项目的web.config文,首先是appSettingsbootstrap
<appSettings>app
<add key="webpages:Version" value="3.0.0.0" />框架
<add key="webpages:Enabled" value="false" />ide
<add key="ClientValidationEnabled" value="true" />函数
<add key="UnobtrusiveJavaScriptEnabled" value="true" />ui
</appSettings>this
先是设置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)在页面中引用资源。