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!
source to share
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 / ...
source to share
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.
source to share