I think there is a problem with URL generation.
Assuming that we have the following controller:
[Route("[action]")]
public class Home : Controller
{
[Route("/")]
public IActionResult Index()
{
return View();
}
[HttpGet]
[Route("{number}")]
public IActionResult Edit(int number)
{
return View();
}
[HttpPost]
public IActionResult Edit()
{
return View();
}
}
The index view generated correct link to Edit action:
<a asp-action="Edit" asp-all-route-data='new Dictionary<string, string>{{"number", "11"}}'>GO TO EDIT</a>
Which is /Edit/11
.
But then in the edit view I am trying to create a form that should post to the same action, but there is no route parameter. So, the URL should be just /Edit
. Instead, I get /Edit/11
which does not reach appropriate action on the controller. I am generating forms in two ways and the result is the same:
<div>
<form asp-action="Edit" method="post">
<button type="submit">submit</button>
</form>
@using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
<button type="submit">submit</button>
}
</div>
What is more, changing POST route template to:
[HttpPost]
[Route("something")]
public IActionResult Edit()
{
return View();
}
Causes link generated for GET to be http://localhost:5253/Edit/something?number=11
which is wrong.
To me, it looks like a bug, but I might have overlooked something. Could you please help me understand this behavior? All endpoints are registered correctly. Is there route precedence involved? If so, then how because those action methods react to separate verbs… I am confused.
Please find project under this link: https://blindsend.io#5m4QCCyXKdchLEos4M1ang;GnFBHbs2xAap6QzxJadwFw==
2
Answers
FYI, you can find aspnet team answer in this question on GitHub: https://github.com/dotnet/aspnetcore/issues/47375#issuecomment-1481063287
I had a test with your sample code, and everything worked well after I comment
[Route("{number}")]
.When we have
[Route("{number}")]
before the Get action method, the request to the Controller will behttps://localhost:7131/Edit/11
, if we comment this attribute, the request will behttps://localhost:7131/Edit?number=11
.The error happened at the form submit operation, and for POST action
public IActionResult Edit()
, the correct request URL should bePOST https://localhost:7131/Edit
, but when the URL in the browser ishttps://localhost:7131/Edit/11
and do the form submit, the submit request will be like below and the issue happened.About the error 405, that means the URL is correct but method is not allowed, in this issue, the "not allowed" points to the Url Routing, to fix the issue, we can comment
[Route("{number}")]
or add[Route("{number}")]
to the POST action.Let’s go back to the normal behavior, see official sample here. The default route mapping defined as
pattern: "{controller=Home}/{action=Index}/{id?}");
and when the Edit Get request becomeMovies/Edit/5
we need to have Movie Controller with Get actionpublic async Task<IActionResult> Edit(int? id)
, theid
is the parameter instead of a route attribute. That’s why I say I comment[Route("{number}")]
at the beginning.