文档章节

使用Areas分离ASP.NET MVC项目

清山博客
 清山博客
发布于 2016/07/15 20:03
字数 1676
阅读 5
收藏 0

为什么需要分离?

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

一个典型的场景

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

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

运行程序访问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
2
3
4
5
6
routes.MapRoute(     //Default Route
     "Default" // Route name
     "{controller}/{action}/{id}" // URL with parameters
     new  { controller =  "Home" , action =  "Index" , id = UrlParameter.Optional },  // Parameter defaults
     new  { controller =  new  NotEqual( "Admin" )}
);

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

第二次改进

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

add area

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

area error

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

/Areas/Admin/AdminAreaRegistration.cs

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

/Global.asax.cs

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

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

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

第三次改进

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

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

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

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

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

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

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

QQ截图未命名

现在运行程序并访问/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

我本地的生成事件为:

1
2
mkdir  "$(SolutionDir)$(SolutionName)\Areas\Admin\Views"
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目录里。

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

转自:http://www.cnblogs.com/dingji/archive/2012/05/30/2506420.html

本文转载自:http://blog.csdn.net/a497785609/article/details/50160605

共有 人打赏支持
清山博客
粉丝 3
博文 142
码字总数 30397
作品 0
广州
私信 提问
Asp.Net MVC3 简单入门第一季(五) 通过Asp.Net MVC的区域功能实现将多个MVC项目部署到一个站点

引子 本文将主要演示怎么将多个Asp.Net MVC项目部署到一个IIS站点中的例子,主要使用的是Asp.Net MVC提供的区域的功能。 Asp.Net MVC提供了区域的功能,可以很方便的为大型的网站划分区域。可...

aicoder
2011/10/12
0
0
1.开始学习ASP.NET MVC

Hello,大家好! 好久没有开始记录博客了,是时候开始分享一下了,这个系列主要为零基础的同学,量身打造的。废话不多说,我们开干! 什么是ASP.NET MVC MVC(Model-View-Controller)--[模型--视...

灰太狼的梦想
02/27
0
0
七天学会ASP.NET MVC(七)——创建单页应用

系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理 七天学会ASP.NET MVC (...

葡萄城控件技术团队
2015/08/11
591
0
asp.net core系列 46 Identity介绍

一. Identity 介绍   ASP.NET Core Identity是一个会员系统,可为ASP.NET Core应用程序添加登录功能。可以使用SQL Server数据库配置身份以存储用户名,密码和配置文件数据。或者,可以使用...

花阴偷移
03/21
0
0
ASP.NET MVC 2 RC 发布

ASP.NET MVC在现有的ASP.NET 运行时的基础上提供了一个新的MVC框架。开发人员可以用MVC设计模式来构建Web应用,做到清晰的概念分离(UI或者视图与业务应用逻辑分离, 应用逻辑和后端数据分离...

红薯
2009/12/17
557
1

没有更多内容

加载失败,请刷新页面

加载更多

Confluence 6 升级中的一些常见问题

升级的时候遇到了问题了吗? 如果你想尝试重新进行升级的话,你需要首先重新恢复老的备份。不要尝试再次对 Confluence 进行升级或者在升级失败后重新启动老的 Confluence。 在升级过程中的一...

honeymoose
今天
2
0
C++随笔(四)Nuget打包

首先把自己编译好的包全部准备到一个文件夹 像这样 接下来新建一个文本文档,后缀名叫.nuspec 填写内容 <?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/201......

Pulsar-V
今天
2
0
再谈使用开源软件搭建数据分析平台

三年前,我写了这篇博客使用开源软件快速搭建数据分析平台, 当时收到了许多的反馈,有50个点赞和300+的收藏。到现在我还能收到一些关于dataplay2的问题。在过去的三年,开源社区和新技术的发...

naughty
今天
5
0
Python3的日期和时间

python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一下这两个库的区别,这可以帮助我们在适当的情况下时候合适的库。 在Python文...

编程老陆
今天
2
0
分布式面试整理

并发和并行 并行是两个任务同时进行,而并发呢,则是一会做一个任务一会又切换做另一个任务。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用,但是每一次,只能有...

群星纪元
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部