I am studying ASP.NET MVC and as my models got a bit complex, I am having somewhat unusual problem.
I have certain model where the items can be in different states. This items may transition from one state to another. Allowed transitions are defined in “Transitions” model/table.
To get the available transitions for particular state, I use the index page where the items are listed and add second foreach
loop to the code:
@foreach (var transition in item.State.Transitions) {
<form asp-action="@transition.TransitionName">
<input type="hidden" asp-for="@item.Id" />
<input type="submit" value="@transition.Description" class="btn btn-warning" />
</form>}
The value of @item.Id
is fetched correctly for each item. However I noticed that the @item.Id
is a “local variable”, and the source code is id="item_Id" name="item.Id" value="1"
.
Correspondingly no id
is transferred to the controller and I can not implement the rest of the code section, which would set new state value based on the used transition.
As I am left with no ideas what to do, any hint will be highly appreciated.
2
Here’s a POST handler that will work with the Form your Razor template generates:
public ActionResult OnPost(string action, Item item)
{
//Seeing a request parameter called “item.Id” OR just “Id” (case
//insensitive), the framework will create an Item instance and
//fill the Id property accordingly.
//
//This is prone to overposting and you should probably not do it
//or at least do additional validation. If your Item class has
//a settable property called “Action” that will also be set!
//Likely you don’t care about that, but it’s worth noting.
//
//The Item object will of course be incomplete and only have the
//values provided by the request.
//
//If no fitting parameter is posted or it is not a valid integer
//the framework will still call this handler and pass it a new
//Item instance with all default values, i.e. Id will be 0.
if (item.Id <= 0)
return new BadRequestResult();
return new ContentResult()
{
StatusCode = 200,
ContentType = @"text/plain; charset=utf-8",
Content = $"Congratulations, you have transitioned Item {item.Id} to {action}.",
};
}
This model binding will work automagically as long as your Item
class has
- a parameterless constructor and
- a settable
Id
property.
Otherwise you’ll get an exception.