Asp.Net MVC routing does not work as expected in 5.1

I need to add culture to the url to support localization in my asp.net mvc application with a url like: sample.com/ en / about
sample.com/ en / product / 2342

I recently upgraded my application from MVC 5.0 to 5.1, but routing did not work as expected, so I created a new asp.net mvc 5.0 test application and got the culture to display in the URL in minutes. However, as soon as I upgrade this test application to MVC 5.1, the culture is no longer created in the links, and if you manually enter it in the URL, you will get a 404 error.

I fixed my test applications 5.0 and 5.1 here . I need to understand why this does not work in MVC 5.1 and how to fix it. Perhaps my understanding of routing is wrong or is it a legitimate mistake with 5.1?

In this test application, the Home / About action has a routing attribute applied to it [Route("about")], and expected that when creating a link for this route, it should be localhost/en/about, but instead, it's simple localhost/about. If you type localhost/en/aboutin the address bar, you will get 404 error in the Mvc 5.1 test application.

Here is the relevant code that works in MVC 5.0:

public class RouteConfig
{
    private const string STR_Culture = "culture";
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;
        routes.MapMvcAttributeRoutes();
        routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        foreach (var item in routes)
        {
            // this works in MVC 5.0
            if (item is Route)
            {
                var route = item as Route;
                if (route.Url.IndexOf("{" + STR_Culture + "}") == -1)
                    route.Url = String.Format("{{{0}}}/{1}", STR_Culture, route.Url);

                //AddCulture(route.Defaults);
            }
        }
    }
    private static void AddCulture(RouteValueDictionary dictionary)
    {
        if (dictionary == null)
            dictionary = new RouteValueDictionary();

        if (dictionary.ContainsKey(STR_Culture) == false)
            dictionary.Add(STR_Culture, "en");
    }
}
+4
source share
1 answer

, . MVC 5.1 . foreach, URL- , "{culture}/" placeholder. , about {culture}/about ..

5.0, System.Web.Routing.Route. 5.1 . LinkGenerationRoute, , . , routes.MapMvcAttributeRoutes();, , . , , : .

foreach Url, NOT , LinkGenerationRoute. , , . , (_innerRoute) , , .

, - .   [Route("{culture}/about")], [Route("{culture}/contact")], [Route("{culture}/product/{productId:int}")] ..

. . this.GetVirtualPath(requestContext, values);

internal class LinkGenerationRoute : Route
{
    private readonly Route _innerRoute; // original route cannot be modified

    public LinkGenerationRoute(Route innerRoute)
        : base(innerRoute.Url, innerRoute.Defaults, innerRoute.Constraints, innerRoute.DataTokens,
        innerRoute.RouteHandler) // original route is effectively cloned by sending individual properties to base class
    {
        if (innerRoute == null)
        {
            throw Error.ArgumentNull("innerRoute");
        }

        _innerRoute = innerRoute;
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        // Claims no routes
        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        // internal route is used for getting the virtual path. fail..
        return _innerRoute.GetVirtualPath(requestContext, values);
    }
}
+1

Source: https://habr.com/ru/post/1533794/


All Articles