28

In MVC3, I have the following areas:

  • Mobile
  • Sandbox

Then i route maps like this:

    context.MapRoute(
        "Sandbox_default",
        "Sandbox/{controller}/{action}/{id}",
        new { controller = "SandboxHome", action = "Index", id = UrlParameter.Optional }

and

    context.MapRoute(
        "Mobile_default",
        "Mobile/{controller}/{action}/{id}",
        new { controller = "MobileHome", action = "Index", id = UrlParameter.Optional }
    );

The problem is this gives urls like:

http://localhost:58784/Mobile/MobileHome

and

http://localhost:58784/Sandbox/SandboxHome

But I want it like this:

http://localhost:58784/Mobile/Home
http://localhost:58784/Sandbox/Home

The problem is when I rename the SandboxHome-Controller to Home, and the MobileHome-Controller to Home, which would give the desired URLs, it won't compile, saying it has two classes for HomeController.

How can I have the same controller name in different areas ?

tereško
  • 58,060
  • 25
  • 98
  • 150
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442

2 Answers2

42

Yes.

As explained by this blog post: http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx

Assuming you have a call to RegisterAllAreas and the AreaRegistration files generated by Visual Studio. All you need to do is the namespace on the default route in global ASAX to prevent conflicts.

//Map routes for the main site. This specifies a namespace so that areas can have controllers with the same name
routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        new[]{"MyProject.Web.Controllers"}
 );

As long as you keep the Area controllers within their own namespaces. This will work.

Rob Stevenson-Leggett
  • 35,279
  • 21
  • 87
  • 141
  • But but... How would you translate this `http://localhost:58784/Mobile/Home` URL using your route definition? I don't think your answer is correct. Which area would it be? Which controller and which action? – Robert Koritnik Feb 21 '11 at 11:47
  • This is the Global.asax route. Once you've specified this namespace you can leave your area routes alone. I'm doing exactly this in my app. – Rob Stevenson-Leggett Feb 21 '11 at 11:54
  • See this blog post from Phil Haack http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx – Rob Stevenson-Leggett Feb 21 '11 at 11:56
  • @Rob yes you're right. When you create areas via Visual Studio it creates area registration classes for you so you can use the code you've provided. You're right. BUT. You should probably also add the call to `RegisterAllAreas()` call. – Robert Koritnik Feb 21 '11 at 12:09
  • @Robert Yes I agree you do still need the RegisterAllAreas and the AreaRegistration files. I'd assumed that the OP would have these already as they are generated by VS. – Rob Stevenson-Leggett Feb 21 '11 at 12:27
  • @Rob Stevenson-Leggett: This way it compiles, but whenever I hit home in any area, it routes to the global home controller. – Stefan Steiger Feb 22 '11 at 09:53
  • @Quandary Are your controllers in their own namespaces? Do you have area registration files for each area and are you calling RegisterAllAreas in Global.Asax.cs? – Rob Stevenson-Leggett Feb 22 '11 at 10:41
  • @Rob Stevenson-Leggett: Yes, yes and yes. – Stefan Steiger Feb 22 '11 at 13:01
  • @Quandary Erm, it sounds like it should be working then. Do you want to post the Global.Asax RegisterRoutes and your AreaRegistration file code? – Rob Stevenson-Leggett Feb 22 '11 at 13:05
  • @Rob Stevenson-Legget: Thanks for the offer, but it's not necessary anymore. Argh, I named the cshtml file for the HomeController Home instead of Index, then it does not issue HTTP error 404 - instead, it goes to the default Index, which is the global one... – Stefan Steiger Feb 27 '11 at 20:51
5

Yes it is but you'll have to change your routing:

context.MapRoute(
    "Default",
    "{area}/{controller}/{action}/{id}",
    new { area = "Mobile", controller = "Home", action = "Index", id = UrlParameter.Optional }
);

You could as well keep both routes but don't forget to define area in your defaults.

Important

Of course you must keep controllers in their own area namespaces:

namespace MyApp.Areas.Mobile.Controllers
{
    public class HomeController : Controller
    {
        ...
    }
}

namespace MyApp.Areas.Sandbox.Controllers
{
    public class HomeController : Controller
    {
        ...
    }
}

Check this link on MSDN and see the walktrough. And don't forget to also check out this MSDN article that talks about area registration, because you will have to call RegisterAllAreas() method.

And since you still want to keep original non-area controllers, you should also read this Phil Haack's article how to do just that (Credit should go to @Rob in his answer for pointing to this blog post first).

Alex
  • 14,104
  • 11
  • 54
  • 77
Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • @Quanday: I added one more link to my answer. But regarding your question in comment you may route those kind of URLs by providing a second route definition without the area where you'd provide a certain area default like `area = "Global"`. But you will as well have to add a constraint on the first route on the area to only match that route when `area` has a certain string value. D'you know what I'm talking 'bout? – Robert Koritnik Feb 21 '11 at 12:05
  • 1
    After about 2 hours of trying, I can say that "{area}/{ is a very bad idea, because if you do that, every url on your site will redirect to the default page in the alphabetically lowest area... – Stefan Steiger Feb 21 '11 at 22:15
  • @Quandary: I seriously doubt that. Defaults are defined by route order not alphabet. But never mind I hope you've solved your problem following the links I've added at the end. – Robert Koritnik Feb 22 '11 at 07:46
  • Whatever order it is, it always routes to the same place, which seems to be the alphabetical lowest area - doesn't have to be that way. The below solution works fine, however. I made another mistake: I named the HomeController action file Home instead of Index, then it always routed to the global home index action - instead of issuing HTTP 404 ... – Stefan Steiger Feb 27 '11 at 20:49