Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Area can't load in MVC - the resource cannot be found

I have a problem. I have a area in MVC 3 called Page that works as it should.

I just added a new Area called Media and now I get "the resource cannot be found" for that new area. I am going crazy, since it looks exactly like the PageArea that works.

Here is the MediaAreaRegistration.cs

public override string AreaName
    {
        get
        {
            return "Media";
        }
    }

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

Here is my global.asax

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );


    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

I am trying to access via localhost/media/, but I am just getting "the resource cannot be found".

Any ideas?

like image 457
Mick johansson Avatar asked Dec 17 '11 21:12

Mick johansson


2 Answers

Check the Namespace of the Controller; In my case; the default route was:

context.MapRoute(
            "Admin_default",
            "Admin/{controller}/{action}/{id}",
            defaults: new {controller = "Home", action = "Index", AreaName="Admin", id = UrlParameter.Optional },
            namespaces: new[] { "MyApp.Admin.Controllers"}
        );

But when I was create the controller, the MVC automatically set "MyApp.WebUI.Areas.Admin.Controllers" as the namespace of the new Controller; I Changed the namespace to what I defined in default route as "MyApp.Admin.Controllers" and application works fine.

like image 66
mesut Avatar answered Oct 16 '22 13:10

mesut


Typically, when you create an area, you will get a somewhat different default route than what is in global.asax. For example, I created a Media area in an MVC3 project, and the default route looks like this:

context.MapRoute(
    "Media_default",
    "Media/{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional }
);

Routes in areas are really no different than routes defined in your global asax, except that they look for controllers in a different namespace. Also, they are loaded before the routes in your global.asax. You can see this because in Application_Start, RegisterAllAreas is invoked before RegisterRoutes.

Typically, this is the URL schema for root controllers with routes defined in your global.asax:

base/ControllerAName/Action1Name
base/ControllerAName/Action2Name
base/ControllerBName/Action6Name

...and so on. This is the "convention" you get with MVC out of the box. Look closely, and you will see that this pattern matches the base route definition in your global asax:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", 
        id = UrlParameter.Optional } // Parameter defaults
);

On the other hand, the convention when you use areas is that your "conventional" URL schema will look like this:

base/AreaName/ControllerAName/Action1Name
base/AreaName/ControllerAName/Action2Name
base/AreaName/ControllerBName/Action6Name

Notice the difference? This is why your default route definition in the area registration looks like this: "Media/{controller}/{action}/{id}"

With all of this said, there is nothing stopping you from deviating from the conventions. It sounds like you want to have an area named Media, and a URL base/media that goes to some action method on some controller in the area. If that is correct, try this -- remembering to put your more specific route before the default route generated by MVC:

context.MapRoute(null,
    "media",
    new { action = "Index", controller = "Media" }
);

context.MapRoute(
    "Media_default",
    "Media/{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional }
);

This means that MVC will match base/media to the Index action method on the MediaController in your Media area, since that route is defined first.

Also, when you create a new area, don't change any namespaces. This will only cause you problems.

Another tip is to not give route names to your routes. Notice how I passed null as the first argument. This is considered good practice -- accessing routes by name can get very messy.

I suggest you try starting a new project, or creating a new area, and trying these suggestions. Grasping routes coming from webforms can be tricky, but once you get a handle on it, I think you will find it superior to the URL-TO-FILE mapping in webforms.

like image 43
danludwig Avatar answered Oct 16 '22 12:10

danludwig