skip to Main Content

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


  1. Chosen as BEST ANSWER

    FYI, you can find aspnet team answer in this question on GitHub: https://github.com/dotnet/aspnetcore/issues/47375#issuecomment-1481063287


  2. 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 be https://localhost:7131/Edit/11, if we comment this attribute, the request will be https://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 be POST https://localhost:7131/Edit, but when the URL in the browser is https://localhost:7131/Edit/11 and do the form submit, the submit request will be like below and the issue happened.

    enter image description here

    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 become Movies/Edit/5 we need to have Movie Controller with Get action public async Task<IActionResult> Edit(int? id), the id is the parameter instead of a route attribute. That’s why I say I comment [Route("{number}")] at the beginning.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search