问题
I have a standard Razor Page that lists all Orders in my database. It's coded pretty standard: IList<Order>
bind property in page model, OnPost method. However, each of the records in a table has a column with a select element that shows the current status of the order, and a button to save the new status if the user decides to change it. Sort of an inline edit of the status for each row.
So I have a foreach loop in my page that cycles through all my orders:
@foreach (var item in Model.Orders)
{
<tr><td>...</td></tr>
<tr>
<td>
<form method="post" class="form-inline">
<input type="hidden" value="@item.Id"/>
<select asp-for="@item.OrderStatusId"
class="form-control form-control-sm"
asp-items="ViewBag.OrderStatusId"></select>
<button type="submit" class="btn btn-secondary btn-sm">
<i class="fas fa-save"></i>
</button>
</form>
</td>
</tr>
}
As you can see, the last column is a form. What I want done is to be able to submit to my OnPost method, the order id (hidden input element in the form) and the selected state (select in element the form). However, these parameters always show up as null in the method. I'm guessing it has something to do with the fact that, because there are multiple asp-for elements for the same property name (one for each form - each order/row), Razor gets confused and doesn't know which one to send.
Is there a way around this?
回答1:
The foreach
loop in your example generates same name
attribute for <select>
elements, which explains why Razor got confused (and it's also invalid HTML). Assumed that Model.Orders
implements IEnumerable
, you should use a for
loop and numeric index for every iteration to generate different <select>
element names:
<form method="post" class="form-inline">
@for (int i = 0; i < Model.Orders.Count; i++)
{
<tr><td>...</td></tr>
<tr>
<td>
<input type="hidden" value="@item.Id"/>
<select asp-for="Model.Orders[i].OrderStatusId" class="form-control form-control-sm"
asp-items="ViewBag.OrderStatusId"></select>
</td>
</tr>
}
<button type="submit" class="btn btn-secondary btn-sm">
<i class="fas fa-save">Save</i>
</button>
</form>
Note: I intentionally put the <form>
& submit <button>
tags outside the loop because it's unnecessary to create multiple <form>
tags (and multiple submit buttons) without setting action
attribute inside for
loop, unless specified otherwise.
Similar issue: How can I bind an array with asp-for tag?
回答2:
The select tag helper will automatically generate a multi-select if the property specified in the asp-for attribute is an IEnumerable.
public class OrderModel
{
public IEnumerable<string> OrderStatusId{ get; set; }
}
Binding the asp-for attribute to the OrderStatusId property as follows:
<select asp-for="OrderStatusId"
asp-items="ViewBag.OrderStatus">
</select>
来源:https://stackoverflow.com/questions/52157469/forms-inside-foreach-loop-in-razor-page