我有一个ASP mvc项目,在编辑页面中使用部分视图。它将适当的值加载到DropDownListFor
中,但是在POST BACK中,这些项突然变为空。
视图使用视图模型来合并两个SQL表。作为该视图模型的一部分,BankListAgentId
类型的List
收集对象用于存储与特定客户端相关的所有代理Id。为了正确地POST和编辑集合对象中的项目,我遵循了Steve Sanderson关于ASP MVC中可变长度对象的博客文章。
这个过程对于代理Id非常有效,但是一旦用户点击"保存",状态代码就全部为空。"
下面是视图 的代码@model Monet.ViewModel.BankListViewModel
@using (Html.BeginForm())
{
<fieldset>
<legend>Stat(s) Fixed</legend>
<table id="fixedRows">
<tr>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
</tr>
@foreach (var item in Model.Fixed)
{
if (!String.IsNullOrWhiteSpace(item.AgentId))
{
@Html.Partial("FixedPartialView", item)
}
}
</table>
<br />
@Html.ActionLink("Add another", "BlankFixedRow", null, null, new { id = "addFixed" })
</fieldset>
}
这是部分
@model Monet.Models.BankListAgentId
@using (Html.BeginCollectionItem("Variable"))
{
<tr>
<td>
@Html.DropDownListFor(model => model.StateCode,
(SelectList)ViewBag.StateCodeList, Model.StateCode)
</td>
<td>
@Html.EditorFor(model => model.AgentId)
@Html.ValidationMessageFor(model => model.AgentId)
</td>
<td>
<a href="#" onclick="$(this).parent().remove();" style="float:right;">Delete</a></td>
</tr>
}
这是视图模型
public class BankListViewModel
{
public int ID { get; set; }
public string BankName { get; set; }
public string LastChangeOperator { get; set; }
public Nullable<System.DateTime> LastChangeDate { get; set; }
public List<BankListAgentId> Fixed { get; set; }
public List<BankListAgentId> Variable { get; set; }
public List<BankListAttachments> Attachments { get; set; }
public BankListViewModel()
{
//Initialize Fixed and Variable stat Lists
Fixed = new List<BankListAgentId>();
Variable = new List<BankListAgentId>();
Models.BankListAgentId agentId = new BankListAgentId();
for (int i = 0; i < 5; i++)
{
Fixed.Add(agentId);
Variable.Add(agentId);
}
//Initialize attachment Lists
Attachments = new List<BankListAttachments>();
Attachments.Add(new BankListAttachments());
}
}
这是从控制器
到编辑页的原始POST public ActionResult Edit(int id)
{
BankListMaster banklistmaster = db.BankListMaster.Find(id);
BankListViewModel viewModel = new BankListViewModel();
viewModel.BankName = banklistmaster.BankName;
viewModel.LastChangeDate = banklistmaster.LastChangeDate;
viewModel.LastChangeOperator = banklistmaster.LastChangeOperator;
List<BankListAgentId> agentId = (from c in db.BankListAgentId
where c.ID == id
select c).ToList();
foreach (var bankListAgentId in agentId)
{
string value = bankListAgentId.FixedOrVariable.Trim();
if (value.Equals("Fixed"))
{
viewModel.Fixed.Add(bankListAgentId);
}
else
{
viewModel.Variable.Add(bankListAgentId);
}
}
viewModel.Attachments = (from c in db.BankListAttachments
where c.ID == id
select c).ToList();
SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
ViewBag.StateCodeList = tmpList;
ViewBag.ID = new SelectList(db.BankListAgentId, "ID", "FixedOrVariable", banklistmaster.ID);
return View(viewModel);
}
public partial class BankListAgentId
{
public string AgentId { get; set; }
public int ID { get; set; }
public string FixedOrVariable { get; set; }
public string StateCode { get; set; }
public virtual BankListMaster BankListMaster { get; set; }
}
您可能希望尝试使用编辑器模板,而不是在循环中注入部分。
@foreach (var item in Model.Fixed)
{
if (!String.IsNullOrWhiteSpace(item.AgentId))
{
@Html.EditorFor(item => item, "FixedPartialView")
}
}
然后放置FixedPartialView。将cshtml放入适当的EditorTemplates文件夹中。我相信,绑定对于框架来说将更加直观。
问题是您使用的是像EditorTemplate一样的Partial视图。部分视图和编辑模板是不同的。你可以把局部视图看作是一个带有一些额外内容的服务器端include。
所以,这里的问题是,您传递给分部的模型与父类中使用的模型不同。
@foreach (var item in Model.Fixed)
{
if (!String.IsNullOrWhiteSpace(item.AgentId))
{
@Html.Partial("FixedPartialView", item)
}
}
当你提交你的模型时,你的局部视图中的助手会呈现代码,就好像模型是固定的一样,所以它会错误地格式化和命名你的局部中的项目。在这种情况下,默认的模型绑定器不知道"item"在一个名为"Fixed"的集合中,因为您已经通过迭代foreach循环删除了该集合的上下文,并且只从包含的项中呈现。
我建议不要使用部分视图,而是使用EditorTemplate,因为这是它们被设计用来处理的(在对象中呈现类型),并且它们会自动处理集合。
或者,如果你想渲染局部,那么不要传递子模型,只让它从父模型中渲染。否则,您将不得不做大量的工作来确保在部分中有正确的命名。
或者,如果您只需要发布这个项目集合,那么您可以确保您的post操作接受IEnumerable<Fixed>
而不是您的父模型。