ASP.NET MVC Area 的使用

  MVC提供Area机制,在同一个项目以内就可以切割出不一样的ASP.NET MVC网站。html

  插入:首先在相同的位置,好比说同一个文件夹(如:Controllers)是不能建立俩个相同名称的文件(如:HomeController),其次在不一样的文件夹中如fold1和fold2,中各自建立一个TestController,程序可以经过编译,但当浏览器视图执行/Test时,网站报出异常,如图:浏览器

由于在默认状况下,路由会同时匹配两个controller,形成没法访问。ide

在项目上,右键,建立区域,问题解决。post

 

出处:http://www.cnblogs.com/SharpL/p/4598589.html网站

=============================================================this

ASP.NET MVC容许使用 Area(区域)来组织Web应用程序,每一个Area表明应用程序的不一样功能模块。这对于大的工程很是有用,Area 使每一个功能模块都有各自的文件夹,文件夹中有本身的Controller、View和Model,但对于管理也增长了必定的难度。url

建立Area

右键工程选择 添加->区域,弹出以下填写Area的对话框:spa

点击添加后,工程目录结构以下:code

和建立一个空MVC工程结构相似,Admin Area 有本身的 Controllers、Models 和 Views 文件夹,不同的地方就是多了一个 AdminAreaRegistration.cs 文件,这个文件中定义了一个叫 AdminAreaRegistration 的类,它的内容以下:htm

复制代码
namespace MvcApplication1.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 }
            );
        }
    }
}
复制代码

系统自动生成的 AdminAreaRegistration 类继承至抽象类 AreaRegistration,并重写了 AreaName 属性和 RegisterArea 方法。在 RegisterArea 方法中它为咱们定义了一个默认路由,咱们也可在这个方法中定义专属于Admin Area的的其余路由。但有一点要注意,在这若是要给路由起名字,必定要确保它和整个应用程序不同。

AreaRegistrationContext 类的 MapRoute 方法和 RouteCollection 类的 MapRoute 方法的使用是同样的,只是 AreaRegistrationContext 类限制了注册的路由只会去匹配当前 Area 的 controller,因此,若是你把在 Area 中添加的 controller 的默认命名空间改了,路由系统将找不到这个controller 。

RegisterArea 方法不须要咱们手动去调用,在 Global.asax 中的 Application_Start 方法已经有下面这样一句代码为咱们作好了这件事:

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

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}
复制代码

调用 AreaRegistration.RegisterAllAreas 方法让MVC应用程序在启动后会寻找全部继承自 AreaRegistration 的类,并为每一个这样的类调用它们的 RegisterArea 方法。

注意:不要轻易改变 Application_Start 中注册方法的顺序,若是你把RouteConfig.RegisterRoutes方法放到AreaRegistration.RegisterAllAreas方法以前,Area 路由的注册将会在路由注册以后,路由系统是按顺序来匹配的,因此这样作会让请求 Area 的 Controller 匹配到错误的路由。

Area的运行

在Area中添加controller、view和model和通常的添加是同样的。在这,咱们在Admin Area中添加一个名为 Home 的controller,代码以下:

public class HomeController : Controller {
        
    public ActionResult Index() {
        return View();
    }
}

而后咱们再为Index Acton添加一个View,代码以下:

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

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <h2>Admin Area Index</h2>
    </div>
</body>
</html>
复制代码

运行应用程序,而后将URL定位到/Admin/Home/Index,下面是运行结果:

到这,咱们已经看到,Area中的的工做流程其实就是和根目录下的流程是同样的。但Area并非一个彻底独立的工做空间,咱们下面来看看。

Controller的歧义问题

试想一下,若是咱们如今在根目录的 Controller 文件夹中也添加一个名为 Home 的 Controller,而后咱们经过把URL定位到 /Home/Index,路由系统能匹配到根目录下的 Controller 吗?

在根目录的 Controllers 文件夹中添加好 HomeController 后,为Index添加View,内容随意:

复制代码
...
<body>
    <div>
        <h2>Root Index</h2>
    </div>
</body>
...
复制代码

路由不改动,咱们使用 RouteConfig.cs 文件中系统定义的默认路由:

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

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}
复制代码

运行程序,将URL定位到 /Home/Index。结果咱们会看到以下错误信息:

出现这个问题是由于路由系统进行匹配的时候出现了Controller同名的歧义。

当Area被注册的时候,Area中定义的路由被限制了只寻找 Area 中的Controller,因此咱们请求 /Admin/Home/Index 时能正常获得 MvcApplication1.Areas.Admin.Controllers 命名空间的 HomeController。然而咱们在RouteConfig.cs文件的RegisterRoutes方法中定义的路由并无相似的限制。

为了解决这个问题,咱们须要在RouteConfig.cs文件中定义的路由中加上对应的 namespaces 参数。RouteConfig.cs 中修改后的路由以下:

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

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { "MvcApplication1.Controllers" }
    );
}
复制代码

运行程序,以下结果说明解决了同名歧义问题:

添加了 namespaces 参数后,路由系统在对这个路由进行匹配时,优先匹配指定命名空间的controller,若是匹配到则即刻中止查找,若是在指定的命名空间下没有匹配到对应的controller,再按照通常的方式进行匹配。

生成Area URL连接

关于Area的URL连接生成,能够分为这么三种状况:第一种是在当前Area生成指向当前Area的连接;第二种是生成指向其余Area的连接;第三种是在某个Area中生成指向根目录的连接。下面是这三种状况生成连接的方法,使用的路由定义是系统默认的。

若是要在Area中生成当前Area的URL连接,直接用下面的方法就行:

@Html.ActionLink("Click me", "About")

它根据当前所在的Area和Controller会生成以下Html代码:

<a href="/Admin/Home/About">Click me</a>

若是要生成其余Area的URL连接,则须要在Html.ActionLink方法的匿名参数中使用一个名为area的变量来指定要生成连接的Area名称,以下:

@Html.ActionLink("Click me to go to another area", "Index", new { area = "Support" }) 

它会根据被指定的Area去找路由的定义,假定在Support Area中定义了对应的路由,那么它会生成以下连接:

<a href="/Support/Home/Index">Click me to go to another area</a>

若是要在当前Area生成指根目录某个controller的连接,那么只要把area变量置成空字符串就行,以下:

@Html.ActionLink("Click me to go to top-level part", "Index", new { area = "" })

它会生成以下Html连接:

<a href="/Home/Index">Click me to go to top-level part</a>

 


参考:《Pro ASP.NET MVC 4 4th Edition》

 

出处:http://www.cnblogs.com/willick/p/3331519.html