0

I have seen some similar questions but i found that i have a diferent problem.

I have a MVC4 project with controllers in the base project and 3 areas. Each area contains a controller named AdminController and a method List.

My problem is when i use a link to go to method List always go through the same controller (e.g. AdminController in Users area) but the view returned is correct.

The structure of the project is like this:

  • Mimbre.Administration (web mvc4 project)
    • Areas
      • Contents
        • Controllers
          • AdminController
        • Models
        • Views
          • Admin
            • List.chtml -ContentsAreaRegistration.cs
      • Logs
        • Controllers
          • AdminController
        • Models
        • Views
          • Admin
            • List.chtml
        • LogsAreaRegistration.cs
      • Users
        • Controllers
          • AdminController
        • Models
        • Views
          • Admin
            • List.chtml
        • UsersAreaRegistration.cs
    • Controllers (base project)
    • Views (base project)

Classes for area registration contains RegisterArea method like this (with apropiate name and namespace according to the current area):

   public override void RegisterArea(AreaRegistrationContext context) {
        context.MapRoute(
            "Contents_default",
            "Contents/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional },
            new string[] { "Mimbre.Administration.Areas.Contents.Controllers" }
        );
    }

Global.asax contains method for register routes for base project

        public static void RegisterRoutes(RouteCollection routes) {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        AreaRegistration.RegisterAllAreas();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new string[]{"Mimbre.Administration.Controllers"}
        );
    }

In index.chtml (in base project) I created links to List method of each area:

<a href="@Url.Action("List", "Admin", new { area = "Contents"})" >Contents list</a>
<a href="@Url.Action("List", "Admin", new { area = "Logs"})" >Logs list</a>
<a href="@Url.Action("List", "Admin", new { area = "Users"})" >Users list</a>

In generated html these links appear like this:

<a href="/Contents/Admin/List/">Contents list</a>
<a href="/Logs/Admin/List/">Logs list</a>
<a href="/Users/Admin/List/">Users list</a>

I think these links are correct, the problem is that any link clicked always takes me through method List in AdminController of Users area, method List in AdminController of another areas are never picked.

This problem could be solved by renaming the name of the controller, unique name for each area, but i really need keep the same controller name in all areas, any idea???

Thans in advance!!!

2 Answers 2

2

Finally I could simulate your problem. The only way that I could have the same output as you (doens't matter what area you're trying to access, but reaching same users controller and responding with right view) is when you register the Area with the wrong controllers namespaces.

/Admin/Home/List route:

namespace SandboxMvcApplication.Areas.Admin.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult List()
        {
            ViewBag.Message = "You've acessed Admin/List";

            return View();
        }
    }
}

/Admin/Home/List view:

@{
    ViewBag.Title = "List";
}

<h1>Admin</h1>

<h2>@ViewBag.Message</h2>

Admin Area Registration:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Admin_default",
        "Admin/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional },
        new string[] { "SandboxMvcApplication.Areas.Admin.Controllers" }
    );
}

/User/Home/List route:

public class HomeController : Controller
{
    public ActionResult List()
    {
        ViewBag.Message = "You've accessed User/List";

        return View();
    }
}

/User/Home/List view:

@{
    ViewBag.Title = "List";
}

<h1>User</h1>

<h2>@ViewBag.Message</h2>

User Area registration:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "User_default",
        "User/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional },
        new string[] { "SandboxMvcApplication.Areas.Admin.Controllers" }
    );
}

With this configuration, my outputs are:

  1. /Admin/Home/List

    Admin

    You've acessed Admin/List

  2. /User/Home/List

    User

    You've acessed Admin/List

Note that the first word works fine (insuring that the right view was rendered but with wrong data comming from list action).

If I correct the user controller namespace in UserAreaRegistration ("SandboxMvcApplication.Areas.User.Controllers"), everything works fine!

Check it out if this could help you or try to explicitly put your namespaces to the right controller. You could also check if the Admins controller are with the right namespace too.

Sign up to request clarification or add additional context in comments.

1 Comment

Felipe, thanks for answer, but AreaRegistration classes have the correct namespace, i don't know if it is a problem of mv4 beta version, temporally i had to rename controllers, different name for each area.
0

You need to append one more setting to your route registration. This will prevent the DefaultControllerFactory from searching for controller in unintended areas.

        routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
        namespaces: new string[]{"Mimbre.Administration.Controllers"} 
    ).DataTokens["UseNamespaceFallback"] = false; 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.