Asp.net MVC 2 Areas. Only one will work
This is my goal:
I need to two (or more) "Areas" for my MVC web app. They would be accessed like so:
/* Home */
http://example.com/
http://example.com/about
http://example.com/faq
http://example.com/contact
/* Admin */
http://example.com/admin
http://example.com/admin/login
http://example.com/admin/account
http://example.com/admin/ect
I would like to organize the project like the following:
MyExampleMVC2AreasProject/
Areas/
Admin/
Controllers/
Models/
Views/
Home/
Shared/
Site.Master
Web.Config
AdminAreaRegistration.cs
Web/
Controllers/
Models/
Views/
Home/
Shared/
Site.Master
Web.Config
WebAreaRegistration.cs
Global.asax
Web.Config
So, in Global.asax
I have:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
Here is WebAreaRegistration.cs
using System.Web.Mvc;
namespace MyExampleMVC2AreasProject.Areas.Web
{
public class WebAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Web";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"WebDefault",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
'AdminAreadRegistration.cs' is set up the same but the url param is Admin/{action}/{id}
.
With the setup above the Web
"Area" w开发者_运维百科orks great (example.com/about, example.com/contact, etc).
What do I need to do to get the Admin
"Area" hooked up with the routes the way I want them? I just get 404
ed now.
I use this AreaRegistrationUtil class. It automatically registers anything which inherits AreaRegistration in any assembly you specify. As an added bonus, it's WAY faster than AreaRegistration.RegisterAllAreas
because it only looks at the assembly you specify.
You probably need to set your namespaces on all your area registrations.
Example
context.MapRoute(
"Admin_default",
"admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "MyExampleMVC2AreasProject.Areas.Admin.Controllers" } // This is area namespace
);
My current solution is here: http://notesforit.blogspot.com/2010/08/default-area-mvc-2.html
I don't like it and would love to get a better solution.
-- copied from URL above:
Implement your Areas as usually, register any routes that you need.
For example:
public class PublicAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Public";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Public_default",
"Public/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional, }
);
}
}
And:
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 {controller = "Overview", action = "Index", id = UrlParameter.Optional }
);
}
}
It's important, that URL should have any prefix, for example http://site.com/PREFIX/{controller}/{action}, because prefix of default Area
will be cropped
Next in Global.asax.cs
:
public class MvcApplication : System.Web.HttpApplication
{
public static string _defaultAreaKey = "DefaultArea";
public static void RegisterDefaultRoute(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//reading parameter DefaultArea from web.config
string defaultArea = ConfigurationManager.AppSettings[_defaultAreaKey];
//check for null
if (String.IsNullOrEmpty(defaultArea))
throw new Exception("Default area isn\'t set");
//select routes from registered,
//which have DataTokens["area"] == DefaultArea
//Note, each Area might have more than one route
var defRoutes = from Route route in routes
where
route.DataTokens != null &&
route.DataTokens["area"] != null &&
route.DataTokens["area"].ToString() == defaultArea
select route;
//cast to array, for LINQ query will be done,
//because we will change collection in cycle
foreach (var route in defRoutes.ToArray())
{
//Important! remove from routes' table
routes.Remove(route);
//crop url to first slash, ("Public/", "Admin/" etc.)
route.Url = route.Url.Substring(route.Url.IndexOf("/") + 1);
//Important! add to the End of the routes' table
routes.Add(route);
}
}
protected void Application_Start()
{
//register all routes
AreaRegistration.RegisterAllAreas();
//register default route and move it to end of table
RegisterDefaultRoute(RouteTable.Routes);
}
}
Do not forget add parameter to web.config:
<configuration>
<appSettings>
<add key="DefaultArea" value="Public"/>
</appSettings>
<!-- ALL OTHER-->
</configuration>
精彩评论