我们先创建一个 ASP.NET web 程序
模板选择 MVC,因为不想使用默认的身份认证我们点击更改身份认证并选择不进行身份认证。
创建的项目结构如下:
查看项目的 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 注册了路由。
- publicRoute MapRoute(stringname,stringurl,objectdefaults,objectconstraints,string[] namespaces)
- {
- if(namespaces ==null&& Namespaces !=null)
- {
- namespaces = Namespaces.ToArray();
- }
- Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
- route.DataTokens[RouteDataTokenKeys.Area] = AreaName;
- booluseNamespaceFallback = (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(newScriptBundle("~/bundles/bootstrap").Include(
- "~/Scripts/bootstrap.js",
- "~/Scripts/respond.js"));
- bundles.Add(newStyleBundle("~/Content/css").Include(
- "~/Content/bootstrap.css",
- "~/Content/site.css"));
我们可以看到两种绑定 ScriptBundle(js 脚本)和 StyleBundle(css),值得注意的是 StyleBundle 方法的参数 virtualPath 需要根据绑定的 css 来设置(设置成 css 文件同目录,避免 css 中的一些相对路径失效),如果 js 脚本中有引用其他脚本也是一样。页面使用时直接通过 Scripts 或 Styles 的静态方法 Render(paths)在页面中引用资源。
来源: http://www.cnblogs.com/ssxg/p/7141883.html