1

I am working with internationalization and long routes. My URLs look like domain/en-us/users/edit/240.

Here is my RouteConfig :

      routes.MapRoute(
            name: "DefaultWithCulture",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
         );

        routes.MapRoute(name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

And here is some Actions in my Controller Users :

    public ActionResult Edit(int id);
    public ActionResult EditPassword(int id);
    public ActionResult EditRights(int id);

I want my Actions EditPassword and EditRights to be accessible via domain/en-us/users/edit/password/240 and domain/en-us/users/edit/rights/240.

I did find a solution, using Route Attributes but with the culture (en-us, es-mx, fr-ca) in my url, it broke it all.

1 Answers1

1

The DefaultWithCulture route you have configured will match 3 or 4 route segments. Your URL (en-us/users/edit/password/240) has 5 route segments, so it will not match.

It will match if you pass it the action method name as you have it configured: en-us/users/editpassword/240.

If you want your URLs to look like your example with 5 segments, you will need to do some additional work. First of all, you need to account for the fact that your action names and URLs don't match. One way to do that is to use the ActionName attribute.

[ActionName("password")]
public ActionResult EditPassword(int id);

[ActionName("rights")]
public ActionResult EditRights(int id);

Then you need some new routes and constraints to match the 4 or 5 segment URLs. The main issue to deal with is that some of your segments overlap. So, you need a constraint so you can tell when the 4th segment is an id or if it is an action method.

Basically, to do this break the 1 route with an optional id parameter into 2 routes with required parameters (since when you add a constraint to id it makes it required).

Then add another route for both the localized and non-localized version that handles the extra edit segment in your URL.

// Route to handle culture with 4 segments, ending in numeric id
routes.MapRoute(
    name: "DefaultWithCulture",
    url: "{culture}/{controller}/{action}/{id}",
    defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index" },
    constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}", id = @"\d+" }
);

// Route to handle culture with 3 segments, to make id optional
routes.MapRoute(
    name: "DefaultWithCulture3Segments",
    url: "{culture}/{controller}/{action}",
    defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index" },
    constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
);

// Route to handle culture with 4 or 5 segments
routes.MapRoute(
    name: "DefaultWithCulture5Segments",
    url: "{culture}/{controller}/edit/{action}/{id}",
    defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Home", action = "Index", id = UrlParameter.Optional },
    constraints: new { culture = "([a-zA-Z]{2}-[a-zA-Z]{2})|[a-zA-Z]{2}" }
);

// Route to handle default with 3 segments, ending in numeric id
routes.MapRoute(name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index" },
    constraints: new { id = @"\d+" }
);

// Route to handle default with 2 segments, to make id optional
routes.MapRoute(name: "Default2Segments",
    url: "{controller}/{action}",
    defaults: new { controller = "Home", action = "Index" }
);

// Route to handle default with 3 or 4 segments
routes.MapRoute(name: "Default4Segments",
    url: "{controller}/edit/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

If you want the extra segment you added to read something other than edit, you will need additional routes because MVC doesn't understand this URL scheme natively.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212