4

I have an MVC 4 application. In that application I have certain Areas, whose URL is not resolved properly. The LocationAreaRegistration.cs is as follows:

context.MapRoute(
            "Location_default",
            "{culture}/{controller}/{action}/{id}",
            new { culture = "en", action = "LocationIndex", id = UrlParameter.Optional },
            new { controller = "(LocationIndex)" }
        );

My route.config is as follows:

routes.MapRoute(
                 name: "Default",
                 url: "{culture}/{controller}/{action}/{id}",
                 defaults: new { culture = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
                 namespaces: new[] { "Locator.Areas.Location.Controllers" }
               ).DataTokens.Add("area", "Location");

I have also tried to change the route.config as below:

routes.MapRoute(
             name: "Default",
             url: "{culture}/{controller}/{action}/{id}",
             defaults: new { culture = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
             namespaces: new[] { "Locator.Areas.Location.Controllers" }
           );

None of the approaches worked and I get The resource cannot be found error.

However when I change the LocationAreaRegistration.cs as follows, it works:

context.MapRoute(
            "Location_default",
            "{culture}/Location/{controller}/{action}/{id}",
            new { culture = "en", action = "LocationIndex", id = UrlParameter.Optional },
            new { controller = "(LocationIndex)" }
        );

But I do not want the URL to contain the Location(Area name). What am I doing wrong?

EDIT

The URLs that I would be going to will be somewhat like:

http://localhost/en/LocationIndex/LocationIndex

Here en is the current culture, Home is the controller name and Index is the action method name.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Senjuti Mahapatra
  • 2,570
  • 4
  • 27
  • 38
  • Good set of MapRoutes, but without knowing the URLs your going to, this question is unanswerable. – Erik Philips Jun 07 '16 at 05:40
  • @ErikPhilips: I have edited my question. Please check – Senjuti Mahapatra Jun 07 '16 at 05:50
  • Your routing is misconfigured. See [Why map special routes first before common routes in asp.net mvc](http://stackoverflow.com/questions/35661062/why-map-special-routes-first-before-common-routes-in-asp-net-mvc/35674633). – NightOwl888 Jun 07 '16 at 06:38
  • @NightOwl888- Yes this will be the case if I redirect to `http://localhost/en/Home/Index`. What if I redirect to `http://localhost/en/LocationIndex/LocationIndex`, then it should get redirected to the LocationIndex action of LocationIndex controller in the area Location, but it is not redirecting. P.S. - Updated my URL in the question – Senjuti Mahapatra Jun 07 '16 at 07:03
  • @Alorika - If using the built-in routing, the URL must contain *something* that routing can identify as the area for the area route to match. That something could be a literal segment or a route constraint (which could use Reflection to only match areas that exist). You said you don't want to use a literal segment, but it is unclear why that is unacceptable. Are you trying to put your default site functionality into the Location area? – NightOwl888 Jun 07 '16 at 08:22
  • @NightOwl888-Yes I will be putting the default site functionality into the Location area – Senjuti Mahapatra Jun 07 '16 at 08:32

1 Answers1

3

To make the Location area the default set of routes for your MVC application, you just need to define your RouteConfig.cs as follows:

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

        routes.MapRoute(
            name: "Default_Localized",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            constraints: new { culture = new CultureConstraint(defaultCulture: "en", pattern: "[a-z]{2}") },
            namespaces: new string[] { "Locator.Areas.Location.Controllers" }
        ).DataTokens["area"] = "Location";

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { culture = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new string[] { "Locator.Areas.Location.Controllers" }
        ).DataTokens["area"] = "Location";
    }
}

Note that this will completely replace any functionality of your default controllers in the application and send all of the requests to the Location namespace.

You should not put any route definitions into your LocationAreaRegistration.cs file. This will ensure they are run last and don't screw with any of your other area routes.

Here is the definition of CultureConstraint. See this answer for more details about how to localize your routes.

using System.Text.RegularExpressions;
using System.Web;
using System.Web.Routing;

public class CultureConstraint : IRouteConstraint
{
    private readonly string defaultCulture;
    private readonly string pattern;

    public CultureConstraint(string defaultCulture, string pattern)
    {
        this.defaultCulture = defaultCulture;
        this.pattern = pattern;
    }

    public bool Match(
        HttpContextBase httpContext, 
        Route route, 
        string parameterName, 
        RouteValueDictionary values, 
        RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.UrlGeneration && 
            this.defaultCulture.Equals(values[parameterName]))
        {
            return false;
        }
        else
        {
            return Regex.IsMatch((string)values[parameterName], "^" + pattern + "$");
        }
    }
}
Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212