Carles Company
Carles Company

Reputation: 7216

ASP.NET Core form with id in the route

I have a small problem with routing and forms on ASP.NET Core 1.0.0. I have the following actions:

[Route("delete/{id:int}")]
[HttpGet]
public async Task<IActionResult> Delete(int id)
{
    Post post = await _postsRepository.GetPost(id);
    return View(new DeletePostViewModel
    {
        PostId=post.Id,
        Title=post.Title
    });
}

[Route("delete"),HttpPost,ValidateAntiForgeryToken]
public async Task<IActionResult> Delete([FromForm]DeletePostViewModel vm,string option)
{
    if (option == "Delete")
        await _postsRepository.DeletePost(vm.PostId);
    return RedirectToAction("Index");
}

And in my view I have the following:

<form asp-action="Delete" asp-controller="AdminPosts" asp-area="Admin" method="post" role="form">
    <div class="form-group">
        <input type="hidden" asp-for="PostId"/>
        <label asp-for="Title"></label>
        <input type="text" asp-for="Title" class="form-control" readonly="readonly"/>
    </div>
    <p>
        <input type="submit" name="option" value="Delete" class="btn btn-danger" />
        <input type="submit" name="option" value="Cancel" class="btn btn-default" />
    </p>
</form>

But it does not resolve the route correctly. The route I get for the form post has also the id, and so it does not resolve the id. I have to either add the id to the form method:

[Route("delete/{id:int}"),HttpPost,ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id,[FromForm]DeletePostViewModel vm,string option)

or I have to remove the id explicitly in the form taghelper:

<form asp-action="Delete" asp-controller="AdminPosts" asp-area="Admin" asp-route-id="" method="post" role="form">

What might I be doing wrong here? Why is it not resolving the route correctly?

Upvotes: 6

Views: 4773

Answers (1)

Kiran
Kiran

Reputation: 57949

Yes, you would have to remove the id explicitly as you have already figured out. This is because id is an ambient value which is why its being used during link generation.

Regarding why this is happening:
In general (either regular or attribute routes), when routes are to be ordered, most specific routes need to come before less specific routes and also routes with larger number of segments come before routes with lesser number of segments. So in your scenario the route delete/{id:int} would be automatically ordered to come before delete. Now since the value for id is ambient, the first route's conditions are met and hence your are seeing the link generated in that way, so to fix it you would need to clear it.

Upvotes: 5

Related Questions