我是MVC的新手。我有一个视图,显示附加到Quote
(QuoteDetails
)的产品。我还有一个Ajax.ActionLink)_
用于“添加产品”,它会为要输入的其他产品加载部分视图。问题是加载局部视图时,不会保存对不在局部视图中的其他产品的编辑。如果未加载部分视图,则会保存对列出的产品的编辑。
以下是主视图的相关代码:
@model CMSUsersAndRoles.Models.QuoteViewModel
....
@Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery.mask.min.js"></script>
@using (Html.BeginForm())
{
....
@Html.HiddenFor(model => model.CustomerId)
@Html.LabelFor(model => model.QuoteId)
@Html.EditorFor(model => model.QuoteId, new { htmlAttributes = new { @readonly = "readonly", @class = "form-control" } })
@Html.ValidationMessageFor(model => model.QuoteId)
.... // more controls for properties of Quote
@Html.LabelFor(model => model.QuoteDetail)
<div id="QuoteDetails">
@for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
@Html.HiddenFor(model => model.QuoteDetail[i].QuoteId, new { htmlAttributes = new { @class = "form-control" } })
....
@Html.EditorFor(model => model.QuoteDetail[i].SKU, new { htmlAttributes = new { @readonly = "readonly", @id = "SKU", @class = "form-control", style = "width: 100px" } })
@Html.EditorFor(model => model.QuoteDetail[i].Amount, new { htmlAttributes = new { @class = "form-control amount", style = "width: 95px" } })
@Html.ValidationMessageFor(model => model.QuoteDetail[i].Amount)
.... // more for controls for properties of QuoteDetail
@Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteDetail[i].QuoteId, quoteDetailId = (Model.QuoteDetail[i].QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.QuoteDetail[i].ProductName,
}, new { @class = "btn btn-danger glyphicon glyphicon-trash" })
</div>
}
@Html.EditorFor(model => model.Subtotal, new { htmlAttributes = new { @class = "form-control subTotal", style = "width: 100px; float:right; clear:left; text-align:right" } })
@Ajax.ActionLink("Add product", "AddProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetail.Count + 1) },
new AjaxOptions
{
UpdateTargetId = "QuoteDetails",
InsertionMode = InsertionMode.InsertAfter
})
}
以下是部分视图:
@model CMSUsersAndRoles.Models.QuoteDetail
@{
ViewBag.Title = "EditQuoteDetail";
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="row" class="row">
<table>
@using (Html.BeginCollectionItem("quoteDetail"))
{
<tr>
@Html.HiddenFor(model => model.QuoteId, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.SKU, new { htmlAttributes = new { @readonly = "readonly", @id = "SKU", @class = "form-control", style = "width: 100px" } })
@Html.DropDownListFor(model => model.ProductId, new SelectList(ViewBag.ProductData, "ProductId", "Name"), "---Select one---", new { style = "width: 300px !important", htmlAttributes = new { @id = "ProductName", @class = "ProductList" } });
.... // more controls for properties of QuoteDetail
@Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.ProductName,
}, new { @class = "btn btn-danger glyphicon glyphicon-trash" })
</tr>
}
</table>
</div>
这是控制器动作:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(QuoteViewModel qvm,
[Bind(Include = "CustomerId,SalesRep,FirstName,LastName,Company,Address1,Address2,City,State,PostalCode,WorkPhone,CellPhone,Email,Discount,PaymentTerms")] Customer customer,
[Bind(Include = "QuoteId,QuoteDetailId,ProductId,ProductName,Amount,ListPrice,Discount,Price")] List<QuoteDetail> quoteDetails,
[Bind(Include = "QuoteId,CustomerId,Subtotal,Tax,Total,QuoteDate,GoodUntil,QuoteSent,DateApproved,DateOrdered")] Quote quote)
{
....
}
任何人都可以帮忙吗?任何帮助将不胜感激。
答案 0 :(得分:1)
您在此处使用了两种不同的技术来生成导致问题的集合。
在主视图中,您有一个for
循环来为现有项生成控件,这些控件生成从零开始的连续索引器,这是DefaultModelBinder
默认使用的。您的html将包含name
属性,例如
<input name="QuoteDetail[0].QuoteId"..../>
<input name="QuoteDetail[1].QuoteId"..../>
<input name="QuoteDetail[2].QuoteId"..../>
但随后您使用BeginCollectionItem
辅助方法添加新项目,该方法会将收集索引器生成为Guid
,以便新输入(xxx
为Guid
} )
<input name="QuoteDetail[xxxx].QuoteId"..../>
还包括
<input name="QuoteDetail.Index" value="xxxx" ... />
,DefaultModelBinder
用于匹配非零非连续索引器。你不能同时使用这两种技术。
要解决此问题,您可以在for
循环
@for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
....
<input type="hidden" name="QuoteDetail.Index" value="@i" />
}
或更改循环以使用每次迭代中包含BeginCollectionItem
方法的部分视图
@foreach(var item in Model.QuoteDetail)
{
@Html.Partial("xxxx", item) // replace xxxx with the name of your partial
}