1

I have a problem with routing in ASP.NET MVC 5. I create two Areas "Public" and "Admin" and I set Public/NewsController/Index default site in url localhost/Example.WebUI but now I can't use localhost/Example.WebUI/Admin... My code with T4MVC:

AdminAreaRegistration.cs

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 { area = MVC.Admin, controller = MVC.Admin.Hierarchy.Name, action = MVC.Admin.Hierarchy.ActionNames.Index, id = UrlParameter.Optional }               
            );
        }
    }

PublicAreaRegistration.cs

 public class PublicAreaRegistration : AreaRegistration 
        {
            public override string AreaName 
            {
                get 
                {
                    return "Public";
                }
            }

            public override void RegisterArea(AreaRegistrationContext context) 
            {
                context.MapRoute(
                    "Public_default",
                    "{controller}/{action}/{id}",
                    new { controller = MVC.Public.News.Name, action = MVC.Public.News.ActionNames.Index, id = UrlParameter.Optional }
                );
            }
        }

RegistrationRoutes.cs

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { area = MVC.Public.Name, controller = MVC.Public.News.Name, action = MVC.Public.News.ActionNames.Index, id = UrlParameter.Optional },
                namespaces: new[] { "Example.WebIU.Areas.Public.Controllers" }
            );

            routes.MapRoute(
                name: "MyRoute",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = MVC.Admin.Hierarchy.Name, action = MVC.Admin.Hierarchy.ActionNames.Index, id = UrlParameter.Optional },
                namespaces: new[] { "Example.WebIU.Areas.Admin.Controllers" }
            );
        }

And Global.asax

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AutoMapper.Mapper.Initialize(cfg => cfg.AddProfile<AutomapperProfile>());
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }

Can you help me?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Duzy
  • 79
  • 2
  • 8

1 Answers1

2

The issue is that all of your route URLs are exactly the same except for the Admin area. MVC will always use the first matching route and ignore every route that follows, so it is important to both configure the routes in the right order, and to ensure that the route doesn't match any URLs except for the ones it should. This problem and possible solutions for it are best described in Why map special routes first before common routes in asp.net mvc?.

The simplest fix is to use a literal segment in the URL to ensure it only matches a specific set of URLs.

PublicAreaRegistration.cs

public class PublicAreaRegistration : AreaRegistration 
{
    public override string AreaName 
    {
        get 
        {
            return "Public";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context) 
    {
        context.MapRoute(
            "Public_default",
            "Public/{action}/{id}",
            new { controller = MVC.Public.News.Name, action = MVC.Public.News.ActionNames.Index, id = UrlParameter.Optional }
        );
    }
}

RegisterRoutes.cs

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute(
        name: "MyRoute",
        url: "MyRoute/{action}/{id}",
        defaults: new { controller = MVC.Admin.Hierarchy.Name, action = MVC.Admin.Hierarchy.ActionNames.Index, id = UrlParameter.Optional },
        namespaces: new[] { "Example.WebIU.Areas.Admin.Controllers" }
    ).DataTokens["area"] = "Admin";

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { area = MVC.Public.Name, controller = MVC.Public.News.Name, action = MVC.Public.News.ActionNames.Index, id = UrlParameter.Optional },
        namespaces: new[] { "Example.WebIU.Areas.Public.Controllers" }
    );
}

Note you also have MyRoute registered in the wrong order. This route must be placed before Default in order for it to have any effect at all. As previously mentioned, you also need a way to ensure that not all 3 segment URLs will match. The above shows the use of a literal segment to do this, but you could do more advanced matching with a Regex route constraint or a Custom route constraint.

Finally, you are missing the .DataTokens["area"] = "Admin" needed to set the route to a specific area (this is needed if you don't define the route inside of the AdminAreaRegistration class).

NightOwl888
  • 55,572
  • 24
  • 139
  • 212