Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Routing is finding the controller in my areas, but not the views

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.

like image 593
Hamman359 Avatar asked Aug 13 '10 19:08

Hamman359


People also ask

Does the controller return a 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.

Are routes and controllers the same thing?

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.

How does the controller knows which view to return?

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.

CAN controller have multiple views?

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.


2 Answers

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 }
        ));
like image 88
Hamman359 Avatar answered Oct 04 '22 20:10

Hamman359


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" }
);
like image 44
Curt Avatar answered Oct 04 '22 22:10

Curt