MVC Area领域处理以及T4MVC的使用

第一部分:(摘选自http://www.cnblogs.com/HuiTai/archive/2012/07/24/MVC-12.html 辉太

(这部分作者写的很详细,直接摘过来了)

MVC框架支持组织一个web应用程序到的区域,每个区域代表应用程序的功能性组比如账单、客户支持,等等,这在一个大的项目是非常有用的,那里有 一套单一的文件夹,所有的控制器,视图和模型可以变得难以管理。每个MVC区域是有自己的文件夹结构,允许您分开管理。这使得它更显而易见哪个项目元素相 互关联应用程序的功能区域,这有助于多个开发人员同事处理项目而没有彼此胡想不干扰。区域是支持主要通过路由机制。

我们从新新建一个MVCweb应用程序("MVCArea"),创建好项目,我们直接演示怎么给项目添加一个区域进来具体如下图3.-4.

图3.图4.

 

当我们创建好我们的区域之后项目的结构会变成如下图5所示。

 

图 5.

OK这里你可以看一套类似与MVC文件机制东东出来,这个就是我们创建的区域关于这个东西后面慢慢来学习他,我们现在只关心他那个自动创建 AdminAreaRegistration.cs的文件里面是怎么一回事,不看内容就凭着这个名字猜一下,大概就路由扯上关系了。OK,打开看 看,AdminAreaRegistration.cs的代码如下:

复制代码
using System.Web.Mvc;

namespace MvcArea.Areas.Admin
{
    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 }
            );
        }
    }
}
复制代码

OK,可以看出上面代码我加粗标识的RegisterArea方法十分有意思,在这个区域里注册一个路由的URL模式"  Admin/{controller}/{action}/{id}",当然我们可以在这里定义其他的URL模式,但是你要知道你这这里定义的话只在该区 域里有效,也就是你额外定义的路由机制的持有权在该区域内。

我们不需要采取任何行动来确保这个注册方法被调用。因为Global.asax文件里的Application_Start方法在我们创建区域的时 候为自动为我们注册进去,那么我们来打开Global.asax文件里的Application_Start方法看看,具体代码如下:

复制代码
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
复制代码

可以看到是OK的,接下我们在我们创建的Admin区域里添加一个控制器("Controller")和方法("Action")和一些视图("View")来看看效果,首先添加一个控制器("Controller"),如下图6.

图6.创建HomeController,具体的代码如下:

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcArea.Areas.Admin.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Admin/Home/

        public ActionResult Index()
        {
            return this.View();
        }

    }
}
复制代码

OK,我们在创建一个视图,如下图7.

图7。创建好Index.cshtml,页面的代码如下:

@{
    ViewBag.Title = "Index";
}

<h2>Admin Area Index</h2>

OK,我们试着运行一下我们的Web项目,并且访问一下他的路由" /Admin/Home/Index",结果如下图8.

图8.

貌似我们撒了一个谎言,我们试着访问一下我们web项目的根路径看看什么效果,运行如下图9.

图9.

OK,MVC路由机制一下找到了2个"HomeController"这下不知道去那个,就出错了!

当一个地区注册,任何路由,我们定义仅限于名称空间关联该区域。这就是我们为什么请求" /Admin/Home/Index "的时候。路由机制找到"HomeController"的命名空间MvcArea.Areas.Admin.Controllers。但 是 Global.asax文件的机制可不是这个样子的,来看看我们默认的 Global.asax文件是怎么搞的,具体代码如下:

复制代码
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }
复制代码

名为default的路由转换传入的URL从浏览器到主控制器HomeController行动上Index方法。在这一点上,我们得到一个错误, 因为有没有命名空间的限制这条路线和MVC框架,可以看到两个的HomeController类。所以我们就可以看到上面悲剧发生,我们对 Global.asax文件做简单的处理,具体操作如下:

复制代码
 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
                new[] { "MvcArea.Controllers" } //指定命名空间
            );

        }
复制代码

这种变化,确保在控制器的主要项目,给予优先解决的请求。

MVC框架中检测到当前的请求与特定的区域, 然后出站的URL生成将会找到一个匹配只有在路线定义为该领域。比如在我们的Index.cshtml修改如下代码所示:

复制代码
@{
    ViewBag.Title = "Index";
}

<h2>Admin Area Index</h2>
@Html.ActionLink("Cilck me", "About")
复制代码

运行项目,可以看到如下图10的生成的连接.

图10.

当然也可以修改如下代码所示(创建一个链接到一个动作在不同的区域,或没有区域内,您必须创建一个变量调用地区并使用它来指定区域的名字你想要的):

复制代码
@{
    ViewBag.Title = "Index";
}

<h2>Admin Area Index</h2>
@Html.ActionLink("Cilck me", "About")
<br />
@Html.ActionLink("Click me to go to another area", "Index", new { area = "Support" })
复制代码

运行的效果如下图11.

图11.

 

第二部分:(以下为个人添加)

在领域内部,各个action的访问和不使用领域时相同,只要指定action和controller即可

@Html.ActionLink("文字","ActionName","ControllerName",new{可选参数})

但是在领域间进行交互访问时,必须包含领域的路由信息,否则只能在当前领域进行查找。例如我们在首页上添加一个链接,访问Admin领域的Index页面,写法应该为:

@Html.ActionLink("test","Index","Home",new{area="Admin"},null)

我们使用 area=“Admin”来指明要访问的领域。Admin为领域名称,必须和AdminAreaRegistration.cs中的AreaName相同。

但是这样还存在另一个问题,比如在维护时修改了Controller或者Action的名称,而没有修改View中相应的链接,程序运行时将出现严重错误。在此推荐使用T4MVC,它可以很好的管理控制器、方法和视图。

在工程项目上右键点击“Manage NuGet packages..”选择安装T4MVC,安装成功后,会在项目下生成:

  • T4MVC.tt
  • T4MVC.settings.t4

T4MVC为每一个Controller创建了一个部分类,通过其中的方法我们可以很方便的取得控制器、方法或者视图。

(注:如果添加了新的文件以后,T4MVC没有更新,则右键点击 .tt文件选择Run Custom Tool,这时整个项目都会被重新编译。)

例如上面提到的跨领域访问的链接:

@Html.ActionLink("test","Index","Home",new{area="Admin"},null)
使用T4MVC以后简化为:
@Html.ActionLink("A_admin", MVC.Admin.Home.Index())

而且在View中也可以使用智能感知,非常方便。

posted @ 2012-07-25 10:20  Johnny Yan  阅读(9337)  评论(1编辑  收藏  举报