views:

41

answers:

3

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: 

Nevermind! Should have read your question more closely before I attempted to answer.

Roberto Hernandez
+1  A: 

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" }
);
Curt
A: 

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 }
        ));
Hamman359