今天闲逛时看到MVC 2.0的一些新特性,其中一样就是:提供域划分功能(Areas)。MVC 1.0刚发布的时候,我就为这个东西纠结过一段时间,后来在老外的Blog上看到了一个简单的解决方案,一直都在用,现整理出来,给有需要的同学做个参考。
园子里对这个功能关注的人好象不是很多,所以对此功能稍做一下解释。域划分简单的说就是按功能来划分模块。如用户模块(User)及文章模块(Article),每个模块都有好几个Controller,也许我们需要把模块分别放在独立的命名空间下。在Url上,模块划分体现为:/{Area}/{Controller}/{Action}。(可能我说的不大清楚,尚不明白的请自行到网上搜索)
以下为步骤:
1.把Controller按模块分类。
2.为模块设计路由
3.更换模板引擎(见上图)
4.将视图移至Area文件夹(路径为/{Area}/{Controller}/{Action})
以下为实现
1.为路由添加area
代码
using
System.Web.Routing;
namespace Madnet.DevMvc
{
public static class RouteHelper
{
public static void CreateArea( this RouteCollection routes, string areaName, string [] controllersNamespace, params Route[] routeEntries)
{
foreach (var route in routeEntries)
{
if (route.Constraints == null ) route.Constraints = new RouteValueDictionary();
if (route.Defaults == null ) route.Defaults = new RouteValueDictionary();
if (route.DataTokens == null ) route.DataTokens = new RouteValueDictionary();
route.Constraints.Add( " area " , areaName);
route.Defaults.Add( " area " , areaName);
route.DataTokens.Add( " namespaces " , controllersNamespace);
if ( ! routes.Contains(route)) // To support "new Route()" in addition to "routes.MapRoute()"
routes.Add(route);
}
}
}
}
namespace Madnet.DevMvc
{
public static class RouteHelper
{
public static void CreateArea( this RouteCollection routes, string areaName, string [] controllersNamespace, params Route[] routeEntries)
{
foreach (var route in routeEntries)
{
if (route.Constraints == null ) route.Constraints = new RouteValueDictionary();
if (route.Defaults == null ) route.Defaults = new RouteValueDictionary();
if (route.DataTokens == null ) route.DataTokens = new RouteValueDictionary();
route.Constraints.Add( " area " , areaName);
route.Defaults.Add( " area " , areaName);
route.DataTokens.Add( " namespaces " , controllersNamespace);
if ( ! routes.Contains(route)) // To support "new Route()" in addition to "routes.MapRoute()"
routes.Add(route);
}
}
}
}
2.改造模板引擎,以满足基于area的模板路径搜索
代码
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace Madnet.DevMvc
{
public class DefaultViewEngine: WebFormViewEngine
{
public DefaultViewEngine()
: base ()
{
ViewLocationFormats = new [] {
" ~/{0}.aspx " ,
" ~/{0}.ascx " ,
" ~/Views/{1}/{0}.aspx " ,
" ~/Views/{1}/{0}.ascx " ,
" ~/Views/Shared/{0}.aspx " ,
" ~/Views/Shared/{0}.ascx " ,
};
MasterLocationFormats = new [] {
" ~/{0}.master " ,
" ~/Shared/{0}.master " ,
" ~/Views/{1}/{0}.master " ,
" ~/Views/Shared/{0}.master " ,
};
PartialViewLocationFormats = ViewLocationFormats;
}
#region IViewEngine Members
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
ViewEngineResult areaResult = null ;
if (controllerContext.RouteData.Values.ContainsKey( " area " )) {
string areaPartialName = FormatViewName(controllerContext, partialViewName);
areaResult = base .FindPartialView(controllerContext, areaPartialName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
string sharedAreaPartialName = FormatSharedViewName(controllerContext, partialViewName);
areaResult = base .FindPartialView(controllerContext, sharedAreaPartialName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
}
return base .FindPartialView(controllerContext, partialViewName, useCache);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
ViewEngineResult areaResult = null ;
if (controllerContext.RouteData.Values.ContainsKey( " area " )) {
string areaViewName = FormatViewName(controllerContext, viewName);
string masterAreaViewName = FormatMasterViewName(controllerContext, masterName);
areaResult = base .FindView(controllerContext, areaViewName, masterAreaViewName, useCache);
if (areaResult != null && areaResult.View != null )
{
return areaResult;
}
areaResult = base .FindView(controllerContext, areaViewName, masterName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
string sharedAreaViewName = FormatSharedViewName(controllerContext, viewName);
areaResult = base .FindView(controllerContext, sharedAreaViewName, masterAreaViewName, useCache);
if (areaResult != null && areaResult.View != null )
{
return areaResult;
}
areaResult = base .FindView(controllerContext, sharedAreaViewName, masterName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
}
return base .FindView(controllerContext, viewName, masterName, useCache);
}
#endregion IViewEngine Members
private static string FormatViewName(ControllerContext controllerContext, string viewName)
{
string controllerName = controllerContext.RouteData.GetRequiredString( " controller " );
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " / " + controllerName + " / " + viewName;
}
private static string FormatSharedViewName(ControllerContext controllerContext, string viewName)
{
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " /Shared/ " + viewName;
}
private static string FormatMasterViewName(ControllerContext controllerContext, string masterName)
{
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " /Masters/ " + masterName;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace Madnet.DevMvc
{
public class DefaultViewEngine: WebFormViewEngine
{
public DefaultViewEngine()
: base ()
{
ViewLocationFormats = new [] {
" ~/{0}.aspx " ,
" ~/{0}.ascx " ,
" ~/Views/{1}/{0}.aspx " ,
" ~/Views/{1}/{0}.ascx " ,
" ~/Views/Shared/{0}.aspx " ,
" ~/Views/Shared/{0}.ascx " ,
};
MasterLocationFormats = new [] {
" ~/{0}.master " ,
" ~/Shared/{0}.master " ,
" ~/Views/{1}/{0}.master " ,
" ~/Views/Shared/{0}.master " ,
};
PartialViewLocationFormats = ViewLocationFormats;
}
#region IViewEngine Members
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
ViewEngineResult areaResult = null ;
if (controllerContext.RouteData.Values.ContainsKey( " area " )) {
string areaPartialName = FormatViewName(controllerContext, partialViewName);
areaResult = base .FindPartialView(controllerContext, areaPartialName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
string sharedAreaPartialName = FormatSharedViewName(controllerContext, partialViewName);
areaResult = base .FindPartialView(controllerContext, sharedAreaPartialName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
}
return base .FindPartialView(controllerContext, partialViewName, useCache);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
ViewEngineResult areaResult = null ;
if (controllerContext.RouteData.Values.ContainsKey( " area " )) {
string areaViewName = FormatViewName(controllerContext, viewName);
string masterAreaViewName = FormatMasterViewName(controllerContext, masterName);
areaResult = base .FindView(controllerContext, areaViewName, masterAreaViewName, useCache);
if (areaResult != null && areaResult.View != null )
{
return areaResult;
}
areaResult = base .FindView(controllerContext, areaViewName, masterName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
string sharedAreaViewName = FormatSharedViewName(controllerContext, viewName);
areaResult = base .FindView(controllerContext, sharedAreaViewName, masterAreaViewName, useCache);
if (areaResult != null && areaResult.View != null )
{
return areaResult;
}
areaResult = base .FindView(controllerContext, sharedAreaViewName, masterName, useCache);
if (areaResult != null && areaResult.View != null ) {
return areaResult;
}
}
return base .FindView(controllerContext, viewName, masterName, useCache);
}
#endregion IViewEngine Members
private static string FormatViewName(ControllerContext controllerContext, string viewName)
{
string controllerName = controllerContext.RouteData.GetRequiredString( " controller " );
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " / " + controllerName + " / " + viewName;
}
private static string FormatSharedViewName(ControllerContext controllerContext, string viewName)
{
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " /Shared/ " + viewName;
}
private static string FormatMasterViewName(ControllerContext controllerContext, string masterName)
{
string area = controllerContext.RouteData.Values[ " area " ].ToString();
return " Views/ " + ( string .IsNullOrEmpty(area) ? "" : (area + " / " )) + " /Masters/ " + masterName;
}
}
}
--------------------------------------
http://www.qwolf.com/