在MVC Razor视图的foreach循环中使用DropDownListFor时出错

本文关键字:DropDownListFor 出错 循环 Razor MVC 视图 foreach | 更新日期: 2023-09-27 18:10:00

我试图在ASP中创建一个简单的表单。MVC,它显示了一个报价列表,并允许用户通过从下拉列表中选择一个人来创建工作订单,并将该报价分配给他,然后一次性提交表单。

我的问题是我在foreach循环中使用DropDownListFor会导致错误,我不认为我是在正确的方式。

一个(稍微简化的)报价是这样的:

public class QuoteItem
{
    public QuoteItem()
    {
        this.IsWorkOrder = false;
    }
    [Key]
    public int QuoteItemCostID { get; set; }
    public string Item { get; set; }
    public decimal? Subtotal { get; set; }
    public bool IsWorkOrder { get; set; }
    [NotMapped]
    public string AssignedTo { get; set; }
}

我有一个视图模型配置如下:

public class UnassignedWorkOrdersViewModel
{
    public IEnumerable<QuoteItemCost> QuoteItemCosts { get; set; }
    public IEnumerable<SelectListItem> Trades { get; set; }
}

和一个像这样的控制器动作:

public ActionResult Unassigned(int id = 0)
{
    var trades = db.UserProfiles.Where(u => u.Typpe == "Trade").ToArray().Select(x => new SelectListItem
    {
        Value = x.FirstName + " " + x.LastName,
        Text = x.FirstName + " " + x.LastName
    }).ToList();

    var quoteItems = db.QuoteItems
        .Where(x => x.IsWorkOrder == false)
        .ToList();
    UnassignedWorkOrdersViewModel viewModel = new UnassignedWorkOrdersViewModel
    {
        Trades = trades,
        QuoteItemCosts = quoteItemCosts
    };
    return View(viewModel);
}

我的问题是,在我看来,我试图显示每个工作订单和旁边的交易下拉列表,我认为我这样做的方式是将类属性"assigned"映射到下拉列表中的值,但这不起作用,因为下拉列表期望LINQ表达式作为第一个参数:

@model Project.ViewModels.UnassignedWorkOrdersViewModel
@if (Model.QuoteItemCosts.Any())
{
    using (Html.BeginForm("Unassigned", "WorkOrder", FormMethod.Post, null))
    {
    @Html.AntiForgeryToken()
    <table>
        @foreach (var item in Model.QuoteItemCosts)
        {
            <tr>
                <td style="width:100px;">
                    <b>Item:</b> @item.Item
                </td>
                <td style="width:200px;">
                    <b>Total:</b> @item.Subtotal
                </td>
                <td>
                    <b>Assign:</b>
                    @Html.DropDownListFor(
                        item.AssignedTo,  // THIS LINE CAUSES AN ERROR 
                        Model.Trades,
                        "", new { @id = "ddlStatus", @style = "width:100%" })
                </td>
            </tr>
        }
    </table>
}

我如何解决这个问题,我是否以正确的方式处理这个问题?在表单提交时,我应该期望返回ViewModel,它将返回我所有的QuoteItems,但是如果用户从下拉列表中选择了一个人,则有一个assigndto条目。

编辑:

Andrei下面的建议帮助并引导我找到了另一个解决方案,我的DropDownListFor现在看起来像这样:

 @Html.DropDownListFor(
                        m => m.QuoteItemCosts.First(q => q.QuoteItemCostID == item.QuoteItemCostID).AssignedTo,
    Model.Trades,
    "", new { @id = "ddlStatus", @style = "width:100%" })

但是当我提交表单时,视图模型是空的:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Unassigned(UnassignedWorkOrdersViewModel viewModel)
    {
        // My viewModel is null
        return RedirectToAction("Index");
    }

我已经更新了我的剃刀代码,包括一个Html。

在MVC Razor视图的foreach循环中使用DropDownListFor时出错

为了使一切正确,您需要在这里使用常规的for循环:

@for (int i = 0; i < Model.QuoteItemCosts.Count; i++)
{
    <tr>
        <td style="width:100px;">
            <b>Item:</b> @Model.QuoteItemCosts[i].Item
        </td>
        <td style="width:200px;">
            <b>Total:</b> @Model.QuoteItemCosts[i].Subtotal
        </td>
        <td>
            <b>Assign:</b>
            @Html.DropDownListFor(
                m => m.QuoteItemCosts[i].AssignedTo,  // THIS LINE CAUSES AN ERROR 
                Model.Trades,
                "", new { @id = "ddlStatus", @style = "width:100%" })
        </td>
    </tr>
}

现在,你可能想知道为什么不保留foreach而只使用m => item.AssignedTo。这是一个非常众所周知的问题与foreach循环在ASP。. NET MVC视图。这里的问题是,上面的表达式将生成一个具有错误名称属性的select标记,并且在发布表单时您将无法收到其值。但是,使用常规for循环生成的名称是正确的。