ASP.NET MVC5 MS_DirectRouteMatches Routing Annotation

I have a little problem with ASP.NET and MVC5 (I am starting with MVC.NET). Everything worked fine until yesterday! But today I don't know why, I'm having problems with "Custom Route Annotations".

I have a "Prodouits" controller with this action:

[Route("{culture}/Produits/{nom_groupe}/{nom}-{id}")]
public ActionResult Detail(string nom_groupe, string nom, string id)
{
    // ...   
    return View();
}

      

In my views, when I call "Url.Action (...)" the url is good. But when I go to the page RouteData seems to be bad (RouteData is not recovering correctly).

Look at my RouteData: Keys [0] => "MS_DirectRouteMatches" Keys [1] => "Controller"

Values[0] => //A list of only 1 RouteData with my 6 parameters into it...
Values[1] => Produits

      

If I remove my "Custom Route Annotation" everything works fine, but the url is very sad ...

Does anyone have any ideas about the problem and solution? Thanks everyone for the help!

EDIT: More information on the problem. I have a "BaseController" for the language. I am overriding the BeginExecuteCore method. There is a code:

protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
    string cultureName = RouteData.Values["culture"] as string;

    // Attempt to read the culture cookie from Request
    if (cultureName == null)
        cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : null; // obtain it from HTTP header AcceptLanguages

    // Validate culture name
    cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe


    if (RouteData.Values["culture"] as string != cultureName)
    {

        // Force a valid culture in the URL
        RouteData.Values["culture"] = cultureName.ToLowerInvariant(); // lower case too

        // Redirect user
        Response.RedirectToRoute(RouteData.Values);
    }


    // Modify current thread cultures            
    Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
    Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

    return base.BeginExecuteCore(callback, state);
}

      

Thanks for your help :-)

EDIT: No one has a solution? Thanks again!

+3


source to share


2 answers


For attribute routing, route values ​​are stored in a nested route key named "MS_DirectRouteMatches" (as you already learned).

Here's how to get RouteData to work as expected when dealing with attribute routing:



protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
    // DEMO: now cultureNameTest will be null
    string cultureNameTest = RouteData.Values["culture"] as string; 

    var routeData = RouteData;
    if (routeData.Values.ContainsKey("MS_DirectRouteMatches"))
    {
        routeData = ((IEnumerable<System.Web.Routing.RouteData>)RouteData.Values["MS_DirectRouteMatches"]).First();
    }

    // Now cultureName will not be null
    cultureName = routeData.Values["culture"] as string; 

      

I found this solution here: fooobar.com/questions/2162427 / ...

+5


source


You want to make sure the segment variable is {culture}

defined when rendering the link on the page. I suspect that is why the call to create the action link might fail

The MVC routing system, when generating the outbound route URL, always ensures that it can set a value for each required segment variable in the route URL to match the route. If you can't always guarantee this, one way might be to change your link from the default value for the segment variable {culture}

as follows:

[Route("{culture=en-us}/Produits/{nom_groupe}/{nom}-{id}")]



Another option you can try is to define 2 routes using the same action method:

        [Route("{culture}/Produits/{nom_groupe}/{nom}-{id}")]
        [Route("Produits/{nom_groupe}/{nom}-{id}")]
        public ActionResult Detail(string nom_groupe, string nom, string id, string culture = null)
        {
           if(string.IsNullOrWhitespace(culture))    {
              culture = //Resolve a value for culture here
            }
            // ...   
            return View();
        }

      

This way you get the best of both worlds, where if you cannot provide a value for a segment variable {culture}

, then it will match the mapping of the routes of the second attribute, and you can simply resolve the value in the action method.

+1


source







All Articles