Reputation: 494
I am using RouteAttributes in my projects, and they are working correctly, except in this case: I have two similar actions, one accepting two int parameters, and the other accepting just one.
The first one takes the two parameters and uses them to load an object and pass it to the View; The second one just tries to find a default value for the second variable, and redirects to the first action, passing the two variables.
The problem is that in ActionResultExample(int idVar1)
, I expect to be redirected to ControllerExample/Edit/idVar1/Brands/idVar2
; however I am redirected to ControllerExample/Edit/idVar1/Brands?idVar2=idVar2
.
This generates an infinite redirection loop, of course.
Here is the example code:
[Route("ControllerExample/Edit/{idVar1}/Brands/{idVar2}")]
public ActionResult ActionResultExample(int idVar1, int idVar2)
{
var objectForView= ObjectController.Get(idVar1, idVar2);
return View("ActionResultExample", objectForView);
}
[Route("ControllerExample/Edit/{idVar1}/Brands")]
public ActionResult ActionResultExample(int idVar1)
{
...
var idVar2 = getDefaultVar2();
return RedirectToAction("ActionResultExample", //redirects to ControllerExample/Edit/idVar1/Brands?idVar2=idVar2 instead of ControllerExample/Edit/idVar1/Brands/idVar2
new {idVar1= idVar1, idVar2 = idVar2 });
}
Upvotes: 2
Views: 2089
Reputation: 638
Using the same name for all parameters is not supported, as ASP.NET MVC have no way to distinguish if you want to go to the route with idVar1 and idVar2 as routevalues or use idVar2 as querystring value. Change the code to the second method to use another route value name:
[Route("ControllerExample/Edit/{idVar3}/Brands")]
public ActionResult ActionResultExample(int idVar3)
{
var idVar2 = 100;
return RedirectToAction("ActionResultExample",
new { idVar1 = idVar3, idVar2 = idVar2 });
}
This should work as expected.
But, if you are using 2 methods only for providing a default value to idVar2 note that you don't need. You can do:
[Route("ControllerExample/Edit/{idVar1}/Brands/{idVar2=100}")]
To set a default value of 100. Or use a nullable type on the controller:
[Route("ControllerExample/Edit/{idVar1}/Brands/{idVar2?}")]
public ActionResult ActionResultExample(int idVar1, int? idVar2)
Note that the routevalue name ends with a question mark in the route attribute to set that is an optional parameter.
Upvotes: 0
Reputation: 47375
You can do this with 1 route and 1 action method:
Here, we use the ? to denote that the last URL parameter is optional, and we do the same thing in the action method using a default method argument.
[Route("ControllerExample/Edit/{idVar1}/Brands/{idVar2?}")]
public ActionResult ActionResultExample(int idVar1, int? idVar2 = null)
{
var idVar2Int = !idVar2.HasValue ? getDefaultVar2() : idVar2.Value;
var objectForView= ObjectController.Get(idVar1, idVar2Int);
return View("ActionResultExample", objectForView);
}
If you really want to have this as 2 separate action methods, you may need to upgrade to System.Web.Mvc 5.1 (which can be done via nuget). Then, you can use the Order parameter on the RouteAttribute. However, you should also rename at least one of the action methods because in MVC, you should not have 2 GET overloads with the same name:
[Route("ControllerExample/Edit/{idVar1}/Brands/{idVar2}", Order = 1)]
public ActionResult ActionResultExample(int idVar1, int idVar2)
{
var objectForView= ObjectController.Get(idVar1, idVar2);
return View("ActionResultExample", objectForView);
}
[Route("ControllerExample/Edit/{idVar1}/Brands", Order = 2)]
public ActionResult ActionResultExampleWithoutDefaults(int idVar1)
{
...
var idVar2 = getDefaultVar2();
return RedirectToAction("ActionResultExample", //redirects to ControllerExample/Edit/idVar1/Brands?idVar2=idVar2 instead of ControllerExample/Edit/idVar1/Brands/idVar2
new {idVar1= idVar1, idVar2 = idVar2 });
}
Upvotes: 3
Reputation: 1390
I haven't used RouteAttribute yet, but it looks like a order issue.
Check http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#order
The old way of doing routing in .\App_Start\RouteConfig.cs you had to order your routes the right way. And if everything else failed the last route was used.
So using the RouteAttribute you need so set the order for your routes. Maybe it's possible with RouteAttribute maybe it isn't. If it isn't you'll have to fallback to the old way of doing things.
Upvotes: 0