MVC其实也是一种功能和显示的分离,ASP.NET MVC 提供区域功能也是为了更好的按照既定方案组织程序。结合使用Areas和项目,我们可以按照某种划分方法(功能、模块)分离MVC项目,方便我们针对不同的项目进行修改、维护和升级,同时也对通用功能、模块的重用提供便利。
近日阅读了并实践了Lyon.L的文章《使用Areas分离ASP.NET MVC项目》,感觉很好,在这里记录一下我整理出的方法,一方面是避免自己遗忘,另一方面也对实践中的一些小问题做些补充。
使用Areas分离ASP.NET MVC3项目的方法整理
主网站名称为MyCMS,其中有一个功能是博客(Blog)。
开发环境:VIsual Studio 2010 SP1 ,ASP.NET MVC3 (C#)
1 建立解决方案和主项目
在解决方案中建立主网站项目(MyCMS)。
2 建立并改造模块项目
2.1 在解决方案中建立功能模块项目(MyCMS.Blog)。
2.2 删除模块项目MyCMS.Blog根目录下的Global.asax和Web.config两个文件。
3 建立模块项目的同名区域(Areas)
3.1 在主项目MyCMS中建立名为Blog的区域(Areas)。
3.2 删除区域中的Controllers文件夹。4 将模块项目注册到同名区域
4.1 建立注册文件BlogAreaRegistration.cs
有两种方法:
4.1.1 移植主项目区域中的BlogAreaRegistration.cs文件。
将主项目区域Blog中的区域注册文件BlogAreaRegistration.cs剪切到模块项目MyCMS.Blog的根目录中去,并将其命名空间从MyCMS.Areas.Blog修改为MyCMS.Blog。
4.1.2 新建注册类BlogAreaRegistration
首先删除主项目区域Blog中的区域注册文件BlogAreaRegistration.cs。
然后在模块项目(MyCMS.Blog)根目录中新建一个BlogAreaRegistration的类,输入如下内容:
/BlogAreaRegistration.cs
namespace MyCMS.Blog
{
public class BlogAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Blog";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Blog_default",
"Blog/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
5 改造主项目路由设置
主要是为了区分主项目和模块项目中的同名控制器,需要修改主项目根目录下的Global.asax文件,给路由注册方法MapRoute()加上控制器命名空间参数。
/Global.asax
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // 参数默认值
new string[] {"SCCEMS.Controllers"} //加上命名空间参数
);
6 设置模块项目的生成事件
主要是因为MVC3 只会去主项目(包括主项目的区域)中需找视图,因此需要在生成时将模块项目中的视图同步到模块项目的同名区域中区。
方法是在模块项目属性中的生成事件里加上如下命令:
mkdir "$(SolutionDir)$(SolutionName)\Areas\Blog\Views"
xcopy "$(ProjectDir)Views" "$(SolutionDir)$(SolutionName)\Areas\Blog\Views" /S /E /C /Y
7 恢复模块项目中视图的智能感知
按照上述方法分离项目以后,模块项目中的视图会出现智能感知错误,如下图所示:
这是因为原来模块项目中的Web.config文件被删除了。而其中的<compilation>节点中设置了为“cshtml”文件注册的生成提供程序。因此需要在模块项目根目录中增加一个只包含<compilation>节点的Web.config文件。
/Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
</system.web>
</configuration>
8 在主项目中添加对模块项目的引用
最后一步,一定要记得在主项目中添加对模块项目的引用,否则以上工作等于白做。
--更新--
写完这篇发现Lyon.L兄有了新的更彻底的方法:使用MVCContrib,详见他的文章《使用MvcContrib分离ASP.NET MVC项目》。
同时他也提到还可以使用nopCommerce。
看来不断会有更好的方法出现,期待完美的解决方案。