Why do we need separation?
We know that the various parts of the MVC project have clear responsibilities, and compared to the ASP. NET WebForm, the business logic of the MVC project is well separated from the page presentation, which has many advantages, such as testable, easy to expand and so on. However, in the actual development, with the scale of the project constantly expanding, controller controllers are also increasing. If there are more than two-bit controllers under the Controllers folder, the readability and maintainability of the project can be affected by the use of a good naming convention, or the use of subfolders to differentiate between different functions of the controller. Therefore, in some scenarios, it is useful to be able to separate files associated with a function into a separate project. ASP. NET MVC provides the concept of areas (region) to achieve this.
A typical scenario.
Web apps typically have front-end (user-facing) and background (for administrators), and we want URLs that start with/locahost/admin to be admin addresses, so we might have a route like this:
1234567891011 |
routes.MapRoute(
//Admin Route
"Admin"
,
// Route name
"Admin/{controller}/{action}/{id}"
,
// URL with parameters
new
{ controller =
"Admin"
, action =
"Index"
, id = UrlParameter.Optional }
// Parameter defaults
); routes.MapRoute(
//Default Route
"Default"
,
// Route name
"{controller}/{action}/{id}"
,
// URL with parameters
new
{ controller =
"Home"
, action =
"Index"
, id = UrlParameter.Optional }
// Parameter defaults
);
|
Run the program Access Locahost/admin, through the output information of the Routedebugger (ASP. NET MVC Routing Debugging Good Helper Routedebugger) can see that the first route (Admin) matches successfully, The index method of the Admincontroller is called, but think again, the/localhost/admin/index can match the second route (Default), the same can be called the Admincontroller index Method! And so on, the background User management list (/localhost/admin/user/list) is equivalent to (/localhost/user/list).
First-time improvements
We want to achieve the goal that/localhost/admin/admin/index correctly matches the first route, while/localhost/admin/index does not match the second route. Therefore, the default route can be conditionally restricted, referring to Stephen Walther's ASP. NET MVC Tip #30 –create Custom Route Constraints, modifying the default route to:
123456 |
routes.MapRoute(
//Default Route
"Default"
,
// Route name
"{controller}/{action}/{id}"
,
// URL with parameters
new
{ controller =
"Home"
, action =
"Index"
, id = UrlParameter.Optional },
// Parameter defaults
new
{ controller =
new
NotEqual(
"Admin"
)}
);
|
The above route means that Admincontroller does not match the default route. Now run the previous two URLs separately, and you will find that the direct access/admin/index has not matched to any routes. By modifying the NotEqual class, you can easily add multiple controller restrictions for the default route that are excluded. But don't you think that's a big setback?
Second improvement
Here comes the point, using the areas function to separate. Create a new project "Mymvcareasdemo", and then, on the project, right-click Add->areas, enter "Admin" as follows:
Under the Areas/admin/controllers folder, create a new HomeController and add a method for index and a corresponding view file. Another benefit of areas can be found here: You can add controllers with the same name under different areas. Of course, if you run this directly you will get an error:
This situation requires a modification of the AdminAreaRegistration.cs and Global.asax, respectively, for routing plus namespace restrictions:
/areas/admin/adminarearegistration.cs
123456 |
context.MapRoute(
"Admin_default"
,
"Admin/{controller}/{action}/{id}"
,
new { action =
"Index"
, id = UrlParameter.Optional },
new
string
[] {
"MyMvcAreasDemo.Areas.Admin.Controllers"
}
);
|
/global.asax.cs
123456 |
routes.MapRoute(
//Default Route
"Default"
,
// Route name
"{controller}/{action}/{id}"
,
// URL with parameters
new
{ controller =
"Home"
, action =
"Index"
, id = UrlParameter.Optional },
// Parameter defaults
new
string
[] {
"MyMvcAreasDemo.Controllers"
}
);
|
In this way, we can put all the controller and view files related to the background management into/areas/admin, and so on, you can add such as members (Member), blog, forum and other areas. Each part has its own top-level folder, the physical files are separated, management is more convenient.
This approach has improved a lot, but all the files are still in the same project. When the project size is larger, the better development method is to separate the different functional modules into different projects, and finally integrate into a whole. In this way, each project can be independently developed, tested and released.
Third-time improvement
We need to reinvent the existing project:
1. Create a new Mymvcareasdemo.admin MVC3 project above the solution and delete the Global.asax and Web. config two files
2. Create a new Adminarearegistration class in the root directory, and enter the following:
12345678910111213141516171819 |
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 }
);
}
}
|
3. Delete the AdminAreaRegistration.cs file under the Mymvcareasdemo Project/areas/admin folder and the Controllers folder (including HomeController)
4. Create a new HomeController in the controllers of the Mymvcareasdemo.admin project
5. Remember to keep the views below Mymvcareasdemo/areas/admin and refer to the Mymvcareasdemo.admin project within the Mymvcareasdemo project,
Now run the program and access/admin/home/index to discover that the Admin project is in effect. In this way, we can put all the controller related to the background management in this new project. But soon you will find that a new "problem" has arisen:
When you add a new action (such as list) to the HomeController inside the mymvcareasdemo.admin, and then habitually right-"add View" on it, You will find that the new list.cshtml file will appear under Mymvcareasdemo.admin/views/home, and the browser will get an error when you visit/admin/home/list: "The View ' List ' or Its master is not found or no view engine supports the searched locations ... ". Originally it will only in the main program Mymvcareasdemo in the corresponding directory to find the view. As a result, the scaffolding that the MVC framework provides to us is compromised, and of course you can manually add a view to the Mymvcareasdemo/areas/admin/views, Or you can automatically create a view in the Mymvcareasdemo.admin project and copy the past. Is there a better way?
Fourth time improvements
In order for us to automatically sync to the Mymvcareasdemo/areas/admin/views folder in the Mymvcareasdemo.admin auto-generated view, you can use the "build event" Post-build Event ", open the Mymvcareasdemo.admin property, as shown in the following:
My local build event is:
12 |
mkdir "$(SolutionDir)$(SolutionName)\Areas\Admin\Views" xcopy "$(ProjectDir)Views" "$(SolutionDir)$(SolutionName)\Areas\Admin\Views" /S /E /C /Y |
The meaning is very simple, I believe everyone can understand, is to completely copy mymvcareasdemo.admin views folder under All files to Mymvcareasdemo/areas/admin/views.
Now you can get the correct results by visiting/admin/home/list again, and you can see that list.cshtml has been copied into the Mymvcareasdemo/areas/admin/views/home directory.
That's it! We have successfully separated the front-facing and background-oriented modules into two separate projects, hoping to help you!
===update===
Another way to detach: separate ASP. NET MVC project using Mvccontrib
From: http://www.cnblogs.com/dingji/archive/2012/05/30/2506420.html
Detaching an ASP. NET MVC project using areas