I'm trying to use Maarten Balliauw's Domain Route class to map sub-domains to the areas in an MVC2 app so that I have URLs like:
http://admin.mydomain.com/home/index
instead of:
http://mydomain.com/admin/home/index
So far, I've only had partial success. Execution is being routed to the correct controller in the correct area, but it cannot then find the correct view. I'm receiving the following error:
The view 'Index' or its master was not found. The following locations were searched:
~/Views/AdminHome/Index.aspx
~/Views/AdminHome/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
This indicates to me that MVC is looking for the view only in the root views folder and not the views folder within the Area. If I copy the view from the Area's views folder to the root views folder, the page renders fine. This however, completely defeats the purpose of dividing the APP into Areas.
I'm defining the route for the area as:
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Admin"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.Add(
"Admin_Default"
, new DomainRoute(
"admin.localhost"
, "{controller}/{action}/{id}"
, new { controller = "AdminHome", action = "Index", id = UrlParameter.Optional }
));
}
}
I'm confused as to why it is finding the controller within the Area fine, but not the view.
A controller action might return a view. However, a controller action might perform some other type of action such as redirecting you to another controller action.
In a modern framework a router defines a direct connection between a "kind" of possible requests and its processor. By contrast, a controller gets just identifying information, and parses this data in its own context.
This even works without parameters, so at that point, you might wonder how in the world a Controller knows exactly which of your Views to return for a specific Action. The answer is something called View Discovery - a process where ASP.NET MVC will try to guess which View to use, without forcing you to specify it.
Controller is the boss, so a Controller decides which View to be rendered and Views does not / cannot care which Controller requested the View. You can / will absolutely have multiple Views from a Controller.
OK, I figured it out. After downloading the MVC 2 source code and adding it to my solution as outlined here, I stepped through the MVC code. I found that Routes within areas implement the IRouteWithArea interface. This interface adds an 'Area' property to the RouteData which, not surprisingly, contains the area's name. I modified the DomainRoute class so to implement this interface and added a couple of overloaded constructors that took this additional parameter, and it now works exactly as I wanted it to.
The code for registering my route now looks like this:
context.Routes.Add(
"Admin_Default"
, new DomainRoute(
"admin.mydomain"
,"Admin"
, "{controller}/{action}/{id}"
, new { controller = "AdminHome", action = "Index", id = UrlParameter.Optional }
));
If you have share controller names between your areas and your default routes, and it looks like you do, you may need to identify namespaces when you call MapRoute
.
For example, if the top-level namespace of your web application is Web
, the RegisterRoutes
method in Global.asax.cs
file would look something like this:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
null,
new string[] { "Web.Controllers" }
);
and then the RegisterArea
moethod of AdminAreaRegistration.cs
would look something like this:
context.MapRoute(
"Admin_Default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
null,
new string[] { "Web.Areas.Admin.Controllers" }
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With