9

I'm trying to use areas within MVC app, I would like that the default route will be resolved to the HomeController within the admin area but it resolves to the home controller in root site. I added the namespace of the admin HomeController but it still resolved to the root HomeController.

My Route config:

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

        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new {controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] {"MvcApplicationAreas.Areas.Admin.Controllers"}

        );
    }
}

admin area route

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

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

HomeController - Admin area

namespace MvcApplicationAreas.Areas.Admin.Controllers
{
   public class HomeController : Controller
   {

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

   }
}

Any idea why it wouldn't resolve properly? Thanks

spooti
  • 247
  • 2
  • 3
  • 9
  • Can you also share your admin HomeController? – neontapir Jun 20 '13 at 17:46
  • Check this post http://stackoverflow.com/questions/2140208/how-to-set-a-default-route-to-an-area-in-mvc – Bhushan Firake Jun 20 '13 at 17:51
  • I saw that post but it's MVC2, from Pro MVC4 book _"This change ensures that the controllers in the main project are given priority in resolving requests. Of course, if you want to give preference to the controllers in an area, you can do that instead."_ it looks like by stating the namespace it should route to the right HomeController – spooti Jun 20 '13 at 17:59
  • I misunderstood your question the first time I read it, so I've deleted my incorrect answer and submitted a new one which I hope is more helpful. – Anders Abel Jun 23 '13 at 08:10

8 Answers8

39

The most straightforward way is to add a data token to your default route:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new {controller = "Home", action = "Index", id = UrlParameter.Optional }
).DataTokens.Add("area", "Admin");

Simply add

.DataTokens.Add("area", "[your area name]");

to the end of your default route definition.

NovaJoe
  • 4,595
  • 6
  • 29
  • 43
  • this worked for me assuming I did not have duplicate Controllers, eg was not permitted to have two `HomeController` – wal Nov 15 '14 at 06:24
  • 7
    If you have duplicate controllers just add a namespace property. ``namespaces: new[] {"Solution.MyProject.Areas.Admin.Controllers"}`` – Ray Suelzer Mar 11 '15 at 22:10
9

I've tested your code for the area registration and it works and selects the right controller. However, the view resolution finds the view in the root folder, even if the right controller is used.

To test, I used the following home index action in my areas home controller:

public ActionResult Index()
{
    return View(model: "Admin area home controller");
}

Then my index.chstml in /Views/Home:

Root View: @Model

and my index.cshtml in /Areas/Admin/Views/Home:

Admin Area view: @Model

When run, the output is:

Root View: Admin area home controller

So the route makes the home controller in the admin area run, but then thew view resolution goes on and finds the root view instead of the admin view.

So in the end, it is indeed the view selection that is wrong, so your problem is the same as in How to set a Default Route (To an Area) in MVC.

Community
  • 1
  • 1
Anders Abel
  • 67,989
  • 17
  • 150
  • 217
6

This solution will broke your API route. You must have some unique name for each area, like the default area makes it:

context.MapRoute(
         "Common_default",
         "**Common**/{controller}/{action}/{id}",
         new { action = "Index", id = UrlParameter.Optional }
);

The correct solution to default route below:

Web area route:

context.MapRoute(
         "Common_default",
         "Common/{culture}/{controller}/{action}/{id}",
         new {culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Main route which redirect users to the "Common" area:

routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new[] { "SMS.Sender.Areas.Common.Controllers" }
        ).DataTokens.Add("area","Common");
Lev K.
  • 344
  • 4
  • 4
2

Try doing this way....it will help in distinguish.Even if you dont add area="Web", its fine

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", area="Web", id = UrlParameter.Optional },
    new[] { "Nop.Web.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;

Same way

context.MapRoute(
    "Admin_default",
    "Admin/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", area = "Admin", id = "" },
    new[] { "Nop.Admin.Controllers" }
);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Tina
  • 89
  • 1
  • 11
  • Confirmed that `area="Web"` is not required. This MapRoute() overload from RouteCollectionExtensions internally executes `route.DataTokens[RouteDataTokenKeys.Namespaces] = namespaces;` so appears to me as an approach that is more consistent with the framework. Link to source code in question: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/RouteCollectionExtensions.cs#L189 – Manfred Apr 16 '17 at 01:14
1

Add the Index action method in your default root home controller. In the Index action method use "return redirecttoaction" statement for the default area redirection

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

Default route should be

 routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new {controller = "Home", 
action = "Index", id = UrlParameter.Optional}
                );
giri-webdev
  • 525
  • 10
  • 20
0

Easiest way to route from areas from AreaRegistration Page:

context.MapRoute("MainDefault", "Main/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } , new[] { "Namespace.To.Controllers" });

context.MapRoute("ClearPath", "", new { controller = "Home", action = "Index" }, new[] { "Namespace.To.Controllers" });
Abhay Naik
  • 410
  • 3
  • 15
0

In your

RouteConfig.cs

routes.MapRoute("redirect all other requests", "{*url}",
        new {
            controller = "UnderConstruction",
            action = "Index"
            }).DataTokens = new RouteValueDictionary(new { area = "Shop" });
Ahmed Abdelraouf
  • 194
  • 1
  • 13
0

default route is by default route in MVC will call at first because in MVC which route is specified very first it will call like that