为 ASP.NET MVC 项目添加“模块”(module)

来源:互联网 发布:php建站免费空间 编辑:程序博客网 时间:2024/06/08 03:43

先说说何为“模块”,如果你用过 php 的 zend framework 框架就理解这个概念和使用的必要性。举个例子来说,有一个项目,这个项目有前台(给用户访问的模块)和后台(给管理员访问的模块),而前台和后台中又有不同的子模块(页面)。这里仅仅使用 controller 和 action 就显的有点为难了,原因在于,前台和后台中极有可能出现相同名称的 controller,对于这种情况 zf 框架处理的要好些,它引入的 module 的概念。

针对刚才说的例子来讲,就是把前台当做一个 module ,后台当做一个 module。不同的 module 中拥有各自的 controller、view,而不同的 module 中的controller 和 view 可以使用相同的名字,当然,对于 controller 来说就不能在同一个命名空间了。

现在,我要做的就是在 ASP.NET MVC 中实现 zf 的这种机制。


注:ASP.NET MVC 2.0 中已引入 Area 概念,用于实现类似的功能。


一、从路由开始改造

先看我的两个模块的路由配置(后台管理模块:Admin、用户模块:User):

public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            routes.MapRoute(                "Admin",                "Admin/{controller}/{action}/{id}",                new { controller = "Home", action = "Index", id = UrlParameter.Optional },                new string[] { "Controllers.Admin" }            );            routes.MapRoute(                "User",                "{controller}/{action}/{id}",                new { controller = "Home", action = "Index", id = UrlParameter.Optional },                new string[] { "Controllers.User" }            );        }


这里创建二个路由配置:

路径如“Admin/Login/Index”的访问使用第一个配置,即:Controllers.Admin 命名空间中 Login 类的 Index 方法。

路径如“Home/Index”的访问使用第二个配置,即:Controllers.User 命名空间中 Home 类的 Index 方法。

我是这样设置我的项目目录的:

在原有的Controller下创建Admin、User两个文件夹,其中的类所在的命名空间就分别为:Controllers.Admin、Controllers.User


二、继承  WebFormViewEngine

使用 Reflector 查看  C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 2\Assemblies\System.Web.Mvc.dll 中 System.Web.Mvc.WebFormViewEngine 类的构造函数是这样的:

public WebFormViewEngine(){    base.MasterLocationFormats = new string[] { "~/Views/{1}/{0}.master", "~/Views/Shared/{0}.master" };    base.AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.master", "~/Areas/{2}/Views/Shared/{0}.master" };    base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.aspx", "~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.aspx", "~/Views/Shared/{0}.ascx" };    base.AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.aspx", "~/Areas/{2}/Views/{1}/{0}.ascx", "~/Areas/{2}/Views/Shared/{0}.aspx", "~/Areas/{2}/Views/Shared/{0}.ascx" };    base.PartialViewLocationFormats = base.ViewLocationFormats;    base.AreaPartialViewLocationFormats = base.AreaViewLocationFormats;} 

这里就是 mvc 搜索视图的地方,那么我们来继承这个类,并改写搜索的路径:

    public class CustomViewEngine : WebFormViewEngine    {        public CustomViewEngine(string module)        {            base.MasterLocationFormats = new string[] {                "~/Views/" + module + "/{1}/{0}.master",                "~/Views/" + module + "/Shared/{0}.master",                "~/Views/Shared/{0}.master"            };            base.ViewLocationFormats = new string[] {                 "~/Views/" + module + "/{1}/{0}.aspx",                "~/Views/" + module + "/{1}/{0}.ascx",                "~/Views/" + module + "/Shared/{0}.aspx",                "~/Views/" + module + "/Shared/{0}.ascx",                "~/Views/Shared/{0}.aspx",                "~/Views/Shared/{0}.ascx"            };            base.PartialViewLocationFormats = base.ViewLocationFormats;            base.AreaPartialViewLocationFormats = base.AreaViewLocationFormats;        }    }

这里我多加了一个参数,这个参数就是 module 的名称。这里假设 module 为“Admin”,则改写后的功能是这样的:

1、先在 Views/Admin/Controller 中找 action,找不到转第2步

2、在 Views/Admin/Controller/Shared 中找 action,找不到转第3步

3、在 Views/Shared 中找,如果还找不到会报错

这里,不论是 master、aspx、ascx 都是这样找的。


三、创建一个控制器基类

如下类:

    public class CustomController: Controller     {        private static CustomViewEngine customViewEngine;        public CustomController(string module)        {            customViewEngine = new CustomViewEngine(module);            ViewEngines.Engines.Clear();            ViewEngines.Engines.Add(new WebFormViewEngine());            ViewEngines.Engines.Add(customViewEngine);        }    } 

这样我就定义了一个自己的控制器,对于以后 MVC 中创建的控制器都要继承至这个控制器。

功能就不多说了,module 就是模块的名称,任何要继承这个控制器的类都要给这个参数。


四、创建 Controller

现在开始可以使用以上代码了,先在 Controller/Admin 下创建一个控制器:

    [HandleError]    public class LoginController : CustomController    {        public ActionResult Index()        {            ViewData["Message"] = " Admin 模块";            return View();        }        public LoginController()            : base("Admin")        { }    }

很简单是不?


五、再来创建 View

在 Views/Admin/Login 下创建一个 Index.aspx 视图文件:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %><asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">    Admin/Login</asp:Content><asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">    <h2>管理员模块:<%= Html.Encode(ViewData["Message"]) %></h2></asp:Content>


类似的你可以创建 User 模块中的 Controller、View 

现在就可以用 /Admin/Login/Index 看到效果了吧?











原创粉丝点击