1

Recently I have faced the following issue. Let's suppose that we have following controller with GET method inside:

[RoutePrefix("admin-panel")]
public class AdminPanelController : Controller
{
   [Route("places/edit/{placeId}")]
   public ActionResult EditPlace(int? placeId)
   {
     return View("EditPlace", new EditPlaceViewModel(...));
   }
}

Now we can access this method by url:

(...)/admin-panel/places/edit/123

The problem is that the placeId parameter is always null.

If I change the EditPlace method routing rule to following:

[RoutePrefix("admin-panel")]
public class AdminPanelController : Controller
{
   [Route("places/{placeId}/edit")]
   public ActionResult EditPlace(int? placeId)
   {
     return View("EditPlace", new EditPlaceViewModel(...));
   }
}

Everything starts working properly - placeId parameter is being passed successfuly.

What am I missing here? Why can't I use first solution?

Thanks in advance!

@update

OK, I've missed that I have the POST methods with the same routing rules which look like:

[HttpPost]
[Route("places/edit/{placeId}")]
[MultipleSubmitButton(Name = "action", Argument = "NextEditStep")]
public ActionResult NextEditStep(int? placeId, EditPlaceViewModel model)
{
    // do some operations with posted model
    return View("EditPlace", new EditPlaceViewModel(...));
}

[HttpPost]
[Route("places/edit/{placeId}")]
[MultipleSubmitButton(Name = "action", Argument = "PreviousEditStep")]
public ActionResult PreviousEditStep(int? placeId, EditPlaceViewModel model)
{
    // do some operations with posted model
    return View("EditPlace", new EditPlaceViewModel(...));
}

If I comment them out, the problem walk away, but to be honest - I need it due to form generating. Is there any chance to have those 3 methods with the same routing rules?

I have similar controller with similar 3 methods (1 GET & 2 POSTS) but they do not have any route parameters. Anyway this routing works great and behaves as expected. The only difference is that the first one have route parameters and the second does not.

smq93
  • 94
  • 1
  • 9
  • Do you have any other action method with that route pattern ? – Shyju Mar 23 '17 at 19:58
  • Thanks for the feedback - I have another GET method with attribute `[Route("places/add")]` and another one with `[Route("places")]`. – smq93 Mar 23 '17 at 20:05
  • 2
    `admin-panel/places/edit/123` should work as per the code you shared. – Shyju Mar 23 '17 at 20:06
  • 1
    @smq93 include the other actions in the question. provide a [mcve] that can be used to reproduce the problem. – Nkosi Mar 23 '17 at 20:08
  • Could you try with `{placeId:int?}` - `[Route("places/edit/{placeId:int?}")]public ActionResult EditPlace(int? placeId)`? – Win Mar 23 '17 at 20:15
  • How are you confirming `placeId` is null? – mxmissile Mar 23 '17 at 20:25
  • @Nkosi I've just updated the issue description. I've confirmed that by debugging process. – smq93 Mar 23 '17 at 20:57
  • @Win it does not change anything. I've clarified my case more accurately. Look at the update, please. – smq93 Mar 23 '17 at 21:27
  • @smq93 can you confirm that `EditPlace`, `NextEditStep`, and `PreviousEditStep` all have the same route template and belong to the same controller? – Nkosi Mar 23 '17 at 21:42
  • @Nkosi exactly, they belong to the same controller class `AdminPanelController` and all of them have the same route template `[Route("places/edit/{placeId}")]`. They behave just fine but placeId parameter is always null in those three cases. – smq93 Mar 23 '17 at 21:51
  • @smq93 you last statement implies that it is hitting at least one of the action. How are you able to hit the individual action and not get route conflicts? That is the most confusing part of this whole problem for me. – Nkosi Mar 23 '17 at 22:00
  • @Nkosi you can always have the same route for at least 2 actions - GET and POST. The tricky part here is that I have added `MultipleSubmitButton` attribute for 2 POST methods which allows me for POST the form on the same route but with different actions. It also works on another controller where my GET and POST methods don't have any Uri parameters. Like I said, the only problem is that the route parameters are always null. Just take a look: http://stackoverflow.com/a/7111222/5785985 – smq93 Mar 23 '17 at 22:21
  • @smq93, Then that means that its `RouteData` is not being set. hence is it null. Inspect the submitted data. I bet you that `placeId` is not in the dictionary. All the examples shown are using convention-based routing and not attribute routing. – Nkosi Mar 23 '17 at 22:57
  • Show an example of how the POST is submitted. – Nkosi Mar 23 '17 at 23:00

2 Answers2

0
[Route("places/edit/{placeId: int}")]

Try this

Prateik
  • 241
  • 2
  • 6
  • 14
  • While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – manniL Mar 23 '17 at 22:17
0

It's possible to use optional parameters in route, like this:

[Route("places/edit/{placeId?}")]

(edit) https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/#optionals-and-defaults

Thowk
  • 386
  • 4
  • 15