想研究一下这个Areas,在博客园知识库找到这篇文章,先全部搬过来吧,原文地址:http://kb.cnblogs.com/page/144561/

为什么需要分离?

  我们知道MVC项目各部分职责比较清晰,相比较ASP.NET Webform而言,MVC项目的业务逻辑和页面展现较好地分离开来,这样的做法有许多优点,比如可测试,易扩展等等。但是在实际的开发中,随着项目规模的不断扩大,Controller控制器也随之不断增多。如果在Controllers文件夹下面有超过两位数controller,即便采用良好的命名规范,或者用子文件夹的形式区分不同功能的控制器,还是会影响项目的可阅读性和可维护性。因此,在一些场景下,如果能把与某功能相关的文件分离到一个独立的项目中是非常有用的。Asp.Net MVC提供了Areas(区域)的概念达到这一目的。

  一个典型的场景

  Web应用通常会有前台(面向用户)和后台(面向管理员)两部分,我们希望以/locahost/Admin开始的URL都为后台管理地址,因此我们也许会有这样的路由:

  1. routes.MapRoute( //Admin Route
  2. "Admin", // Route name
  3. "Admin/{controller}/{action}/{id}", // URL with parameters
  4. new { controller = "Admin", action = "Index", id = UrlParameter.Optional } // Parameter defaults
  5. );
  6. routes.MapRoute( //Default Route
  7. "Default", // Route name
  8. "{controller}/{action}/{id}", // URL with parameters
  9. new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
  10. );

  运行程序访问locahost/Admin, 通过RouteDebugger(Asp.Net MVC路由调试的好帮手RouteDebugger)的输出信息可以看到,第一个路由(Admin)匹配成功,AdminController的Index方法被调用了,然而再仔细想想,通过/localhost/Admin/Index可以匹配第二个路由(Default),同样可以调用AdminController的Index方法!以此类推,后台用户管理列表(/localhost/Admin/User/List)等同于(/localhost/User/List)。

  第一次改进

  我们要达到一种目的,那就是/localhost/Admin/Admin/Index正确匹配第一个路由,而/localhost/Admin/Index不匹配第二个路由。因此可以对Default路由进行条件限制,参考Stephen Walther的ASP.NET MVC Tip #30 – Create Custom Route Constraints,修改Default路由为:

  1. routes.MapRoute( //Default Route
  2. "Default", // Route name
  3. "{controller}/{action}/{id}", // URL with parameters
  4. new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
  5. new { controller = new NotEqual("Admin")}
  6. );

  上面的路由意思是AdminController不会匹配Default路由。现在分别运行之前的两个URL,会发现直接访问/Admin/Index已经不能匹配到任何路由。通过修改NotEqual类,可以很容易为Default路由添加多个“排除在外”的Controller限制条件。但是,你不觉得这样很挫么?

第二次改进

  这里进入正题,使用Areas这个功能来进行分离。新建一个项目"MyMvcAreasDemo",然后在项目上右键->添加->Areas,输入"Admin",如下:

  在Areas/Admin/Controllers文件夹下面新建HomeController并添加一个Index的方法和对应的View文件。这里可以发现Areas的另一个好处:你可以在不同Areas下面添加相同名称的Controller。当然,如果你直接这么运行会得到一个错误:

  这种情况需要修改一下AdminAreaRegistration.cs和Global.asax,分别为路由加上命名空间限制:

  /Areas/Admin/AdminAreaRegistration.cs

  1. context.MapRoute(
  2. "Admin_default",
  3. "Admin/{controller}/{action}/{id}",
  4. new { action = "Index", id = UrlParameter.Optional },
  5. new string[] { "MyMvcAreasDemo.Areas.Admin.Controllers" }
  6. );

  /Global.asax.cs

  1. routes.MapRoute( //Default Route
  2. "Default", // Route name
  3. "{controller}/{action}/{id}", // URL with parameters
  4. new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
  5. new string[] { "MyMvcAreasDemo.Controllers" }
  6. );

  这样,我们就可以把所有与后台管理相关的Controller和View文件放到/Areas/Admin下面,以此类推,可以添加诸如会员(Member),博客(Blog),论坛(Forum)等多个Areas。各部分都有自己的顶层文件夹,物理文件都分离开来,管理起来比较方便。

  这种方式已经有了很大提高,但是所有的文件还是放在同一个项目里面。当项目规模较大的时候,比较好的开发方式是将不同功能模块按需要独立到不同项目里面,最后再整合成一个整体。这样,每一个项目可以独立开发,测试和发布。

第三次改进

  我们需要对现有项目进行一下改造:

  1.   在解决方案上面新建一个MyMvcAreasDemo.Admin的MVC3项目,并且删除Global.asax和Web.config两个文件

  2.   在根目录新建一个AdminAreaRegistration的类,输入如下内容:

  1. public class AdminAreaRegistration : AreaRegistration
  2. {
  3. public override string AreaName
  4. {
  5. get
  6. {
  7. return "Admin";
  8. }
  9. }
  10. public override void RegisterArea(AreaRegistrationContext context)
  11. {
  12. context.MapRoute(
  13. "Admin_default",
  14. "Admin/{controller}/{action}/{id}",
  15. new { action = "Index", id = UrlParameter.Optional }
  16. );
  17. }
  18. }

  3.   删除MyMvcAreasDemo项目/Areas/Admin文件夹下面的AdminAreaRegistration.cs文件以及Controllers文件夹(包括HomeController)

  4.   在MyMvcAreasDemo.Admin项目的Controllers里面新建一个HomeController

  5.   记得保留MyMvcAreasDemo/Areas/Admin下面的Views,并且在MyMvcAreasDemo项目里面引用MyMvcAreasDemo.Admin项目,如图:

  现在运行程序并访问/Admin/Home/Index可以发现Admin项目生效了。这样,我们可以将所有的与后台管理相关的Controller都放到这个新的项目中来。但是很快你会发现,一个新的“问题”又出现了:

  当你在MyMvcAreasDemo.Admin里面的HomeController添加新的Action(例如List),然后习惯性在上面右键-"Add View"后,你会发现新增的List.cshtml文件会出现在MyMvcAreasDemo.Admin/Views/Home下面,然后当你访问/Admin/Home/List的时候浏览器会得到错误提示:"The view 'List' or its master was not found or no view engine supports the searched locations…"。原来它只会在主程序MyMvcAreasDemo中的对应目录去寻找View。这么一来,MVC框架提供给我们的脚手架功能就大打折扣,当然你可以手动在MyMvcAreasDemo/Areas/Admin/Views中对应添加View,或者在MyMvcAreasDemo.Admin项目中自动生成了View之后再拷贝过去。有没有更好的办法呢?

第四次改进

  为了使我们在MyMvcAreasDemo.Admin自动生成的View自动同步到MyMvcAreasDemo/Areas/Admin/Views文件夹中,可以使用“生成事件(Build Event)”里的“Post-Build Event”,打开MyMvcAreasDemo.Admin的属性,修改如下图所示:

  我本地的生成事件为:

  1. mkdir "$(SolutionDir)$(SolutionName)\Areas\Admin\Views"
  2. xcopy "$(ProjectDir)Views" "$(SolutionDir)$(SolutionName)\Areas\Admin\Views" /S /E /C /Y

  意思其实很简单,相信大家都能看得懂,就是完全复制MyMvcAreasDemo.Admin的Views文件夹下所有文件至MyMvcAreasDemo/Areas/Admin/Views中。

  现在再次访问/Admin/Home/List就可以得到正确结果了,并且你可以发现List.cshtml已经被复制到MyMvcAreasDemo/Areas/Admin/Views/Home目录里。

  至此大功告成!我们已经将面向前台和面向后台的模块成功分离到两个独立的项目中,希望能对您有所帮助!

MVC下为什么要使用Areas的更多相关文章

  1. .net mvc下的Areas和小写Url

    首先是一个站点有前台后台两部分,这个要怎么来做.可以在mvc项目中添加区域(Areas)来实现,当添加一个名为Admin的区域时,项目下多了一个Areas/Admin目录,里边有Controllers ...

  2. MsChart在MVC下的问题

    项目为webform和mvc混用,新建了Areas,在Areas目录下的aspx页面的图表无法显示. 解决方案 第一种方法: 将控件的ImageStorageMode设置为UseImageLocati ...

  3. MVC下判断PC和移动端

    MVC下的PC端和移动端,其实没区别,写法都一样,只是有两点才改变了它们 第一点:就是单击这个页面任何地方的时候判断是移动端还是客户端: 第二点:新建手机端区域Areas(简单来说:Areas就相当于 ...

  4. MVC下压缩输入的HTML内容

    在MVC下如何压缩输出的HTML代码,替换HTML代码中的空白,换行符等字符? 1.首先要了解MVC是如何输出HTML代码到客户端的,先了解下Controller这个类,里面有很多方法,我们需要的主要 ...

  5. ASP.NET MVC下的四种验证编程方式[续篇]

    在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...

  6. ASP.NET MVC下的四种验证编程方式

    ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定 ...

  7. Response.End()在Webform和ASP.NET MVC下的表现差异

    前几天在博问中看到一个问题--Response.End()后,是否停止执行?MVC与WebForm不一致.看到LZ的描述后,虽然奇怪于为何用Response.End()而不用return方式去控制流程 ...

  8. ASP.NET MVC下的四种验证编程方式[续篇]【转】

    在<ASP.NET MVC下的四种验证编程方式> 一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式(“手工验证”.“标注ValidationAttribute特性”.“ ...

  9. ASP.NET MVC下的四种验证编程方式【转】

    ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效 性,我们将针对参数的验证成为Model绑 ...

随机推荐

  1. BMP格式转JPEG格式

    int Bmp2Jpg(const char *bmp_data, const char *jeg_file, const int width, const int height) { int ret ...

  2. Linux测试程序 - 多线程

    #include <sched.h> #include <pthread.h> main(){ pthread_t id0, id1, id2; ret=pthread_cre ...

  3. 【转】hurry_liu 大神STM32移植contiki入门之一:系统介绍和开发环境搭建

    前言: 由于项目的原因,需要在LPC1788(STM32 cortex-M3)上面跑contiki. 之前没有涉及到contiki,不知其为何物.不过这个不是难事,做IT的,每每遇到新事物,都不会处理 ...

  4. Ueditor/自定义配置

    UEditor除 了具有轻量.可定制等优点外,还始终将优化编辑操作.提升用户体验摆在了很重要的位置.在这一点上,除了对编辑器功能.性能.实现细节等不断地改进和追求 创新之外,众多灵活而人性化的自定义配 ...

  5. PowerDesigner中添加约束

    唯一约束 唯一约束与创建唯一索引基本上是一回事,因为在创建唯一约束的时候,系统会创建对应的一个唯一索引,通过唯一索引来实现约束.不过唯一约束更直观的表达了对应列的唯一性,使得对应索引的目的更加清晰,所 ...

  6. Drools学习笔记3—Conditions / LHS—字段约束连接&字段约束操作符

    字段约束连接 用于字段约束 对象内部多个约束连接,采用“&&”(and).“||”(or)和“,”(and) 执行顺序:“&&”(and).“||”(or)和“,” 字 ...

  7. java反射专题二

    一丶Class中常用方法详解 1)getFields() 只能获取到运行时类中及其父类中声明为public的属性 2)getDeclaredFields() 获取运行时类本身声明的所有属性 3)get ...

  8. 类型:linux;问题:linux命令;结果:Linux常用命令大全

    Linux常用命令大全 QQ空间新浪微博腾讯微博人人网豆瓣网百度空间百度搜藏开心网复制更多1997 系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) una ...

  9. xcopy 命令行

    https://www.cnblogs.com/yang-hao/p/6003308.html xcopy-参数详解   XCOPY——目录复制命令  1.功能:复制指定的目录和目录下的所有文件连同目 ...

  10. div的作用

    <div></div>主要是用来设置涵盖一个区块为主,所谓的区块是包含一行以上的数据,所以在<div></div>的开始之前与结束后,浏览都会自动换行, ...