C# – ASP.NET MVC Url.Action and route name value

asp.net-mvcasp.net-mvc-2asp.net-mvc-routingc

I am using asp.net mvc 2 and create localization based on routes.

  1. my route looks like: {culture}/{controller}/{action}
  2. I go to my home controller: en/Home/Index
  3. my home controller view have a links to other controllers:

    <a href='<%= Url.Action("Prods","Products") %>' >Products</a>
    <a href='<%= Url.Action("Index","About") %>' >About</a>
    

First link generated code: /en/Products/Prods but second one generate: /Home/Index

I can't understand why Url.Action skips the {culture} route parameter when I pass value Index in argument action? What am I doing wrong?

Route configuration:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute("Login", // Route name
                "{controller}/Index", // URL with parameters
                new { controller = "Login", action = "Index" } // Parameter defaults
                ).RouteHandler = new SingleCultureMvcRouteHandler();

routes.MapRoute("Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
               );      

Then

foreach (Route r in routes)
{
    if (!(r.RouteHandler is SingleCultureMvcRouteHandler))
    {
       r.RouteHandler = new MultiCultureMvcRouteHandler();

       r.Url = "{culture}/" + r.Url;

       if (r.Defaults == null)
       {
          r.Defaults = new RouteValueDictionary();
       }

       r.Defaults.Add("culture", "en");

       if (r.Constraints == null)
       {
          r.Constraints = new RouteValueDictionary();
       }

       r.Constraints.Add("culture", new CultureConstraint(cultures));
    }
 }

Thanks for all help

Best Answer

When generating URL your best options is to always use the route names because this way you do not get into the subtleties of the algorithm used to select the route that will be used to generate the URL.

My advice if for you not to use Url.Action and instead use Url.RouteUrl which allows you to specify the name of the route that should be used to construct the URL.

By always using route names you also make your code more robust to changes, for example, you can add new routes without having to worry that they might break your existing code for URL generation.