views:

379

answers:

4

Hi,

I have a project that is using MVC areas. The area has the entire project in it while the main "Views/Controllers/Models" folders outside the Areas are empty barring a dispatch controller I have setup that routes default incoming requests to the Home Controller in my area.

This controller has one method as follows:-

public ActionResult Index(string id)
    {
        return RedirectToAction("Index", "Home", new {area = "xyz"});
    }   

I also have a default route setup to use this controller as follows:-

routes.MapRoute(
            "Default",                                              // Default route
            "{controller}/{action}/{id}",
            new { controller = "Dispatch", action = "Index", id = UrlParameter.Optional }
        );   

Any default requests to my site are appropriately routed to the relevant area. The Area's "RegisterArea" method has a single route:-

context.MapRoute(
            "xyz_default",
            "xyz/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }

My area has multiple controllers with a lot of views. Any call to a specific view in these controller methods like "return View("blah"); renders the correct view. However whenever I try and return a view along with a model object passed in as a parameter I get the following error:-

Server Error in '/DeveloperPortal' Application.
The view 'blah' or its master was not found. The following locations were searched:
~/Views/Profile/blah.aspx
~/Views/Profile/blah.ascx
~/Views/Shared/blah.aspx
~/Views/Shared/blah.ascx 

It looks like whenever a model object is passed in as a param. to the "View()" method [e.g. return View("blah",obj) ] it searches for the view in the root of the project instead of in the area specific view folder.

What am I missing here ?

Thanks in advance.

+1  A: 

If this is a routing problem, you can fix it by registering your area routes first. This causes the routing engine to try matching one of the area routes, before matching a root route:

AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);

If I force an error by renaming one of my views folders in my areas application, I get a different error than yours:

The view 'Index' or its master was not found. The following locations 
  were searched:

~/Areas/xyz/Views/Document/Index.aspx
~/Areas/xyz/Views/Document/Index.ascx
~/Areas/xyz/Views/Shared/Index.aspx
~/Areas/xyz/Views/Shared/Index.ascx

...and then the usual root view folders.. 

..which is the pattern of subdirectories it would search if it thought it was in an area.

Robert Harvey
That is done by default in an ASP.NET MVC 2 web application in VS2008. It is part of the default setup of the global.asax
See my edit....
Robert Harvey
Hi Robert,I re-checked all my controller namespaces. They all align with what they should be which is ProjectName.Areas.AreaName.Controllers.
The error you are getting is exactly what I am faced with. The only difference being that I actually have the pertinent views present in the area specific view folder
Perhaps you could new up a RouteValueDictionary in the controller like this: `System.Web.Routing.RouteValueDictionary routeData = RouteData.Tokens`, set a breakpoint, hover over the routeData variable, and see if you're getting an `area` key with the value `xyz`? That would verify that the route data is correct.
Robert Harvey
Note that the error you posted is not the same error I posted. The error I posted actually tries 8 different locations (4 for the area, and 4 for the root).
Robert Harvey
Yea, you're right, mine only target the root.
Basically what I have done is that I had a standard MVC project that I moved in to an area when I migrated to MVC 2.0 So now the root folders are empty barring the controllers that have one root controller that is used to dispatch default requests to the Area that my project now lies under.
The global.asax has one route :- routes.MapRoute( "Default", // Default route "{controller}/{action}/{id}", new { controller = "Dispatch", action = "Index", id = UrlParameter.Optional } ); And the Area "xyz" has its default (even though this area has multiple controllers and views):-context.MapRoute( "Developers_default", "Developers/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } );
For some context, I do have a home controller in the root of my application for the initial (default) home Url. It performs a `RedirectRoute` into an area (specifying the name of the area route), and I stay in that area (or one of the other areas) for the remainder of the session. I only use root controllers for authentication.
Robert Harvey
I'm sorry what are you referring to ? I have controllers only in the area, other than the dispatch controller in the root. When I debug the project, the controllers in the area are the ones getting called. However for some reason when I try to return a View MVC tries to search for that view under the root views folders.
Mind you, I don't use `UrlParameter.Optional` (not yet, anyway), and I think that might figure in here somehow.
Robert Harvey
Yes, this is exactly what I am doing. The dispatch controller is like your root home controller. It performs a redirect to action to a specific controller and an action in the area.
I could do a redirecttoroute instead of a redirecttoaction.
What I am saying is that I think it will work if you use `RedirectToRoute` instead of `RedirectToAction` in your dispatch controller.
Robert Harvey
Nope, that didn't work. I had a redirect to action in my DispatchController "Index" action which I now turned in to return RedirectToRoute("xyz_default",new{controller="Home", action = "Index"}); I get the same error.
Your master page. Should it be in the root views/shared folder or in the area specific views/shared folder ?
My master page is in the root. Currently I am using it for all views.
Robert Harvey
A: 

Solved ! A couple of my "RedirectToAction" calls were not specifying the area name explicitly in the routeobject collection parameter of that method. Weird though, that that is required even though the controllers Redirecting are all in the same area. Also, the HtmlActionLinks work fine when I don't specify the new {area="blah"} in its routeobject collection, so I wonder why the controller action calls to RedirectToAction() need that even though both the calling and the called controller actions are all within the same area.

A: 

Check the generated code at *MyArea*AreaRegistration.cs and make sure that the controller parameter is set to your default controller, otherwise the controller will be called bot for some reason ASP.NET MVC won't search for the views at the area folder

public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "SomeArea_default",
            "SomeArea/{controller}/{action}/{id}",
            new { controller = "SomeController", action = "Index", id = UrlParameter.Optional }
        );
    }
Raphael
A: 

I have the problem you say. When I debug the controler in the other area is called but from there it is unable to find the view. i get the errors saying

Server Error in '/' Application.

The view 'Index' or its master was not found. The following locations were searched: ~/Areas/BpmModel/Views/BpmModel/Index.aspx ~/Areas/BpmModel/Views/BpmModel/Index.ascx ~/Areas/BpmModel/Views/Shared/Index.aspx ~/Areas/BpmModel/Views/Shared/Index.ascx ~/Views/BpmModel/Index.aspx ~/Views/BpmModel/Index.ascx ~/Views/Shared/Index.aspx ~/Views/Shared/Index.ascx

I can't see anything wrong in the RegisterArea method public class Routes : AreaRegistration { public override string AreaName { get { return "BpmModel"; } }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "BpmModel_Default",
            "BpmModel/{controller}/{action}/{id}",
            new { controller = "BpmModel", action = "Index", id = "" }
        );
    }
}

and the controller looks like

public class BpmModelController : Controller { // // GET: /BpmModel/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult InitModel(string projectId)
    {
        return View();
    }


}

and i created a view by doing a right mouse button and Add view on the Index() mehod.