我正在运行Visual Studio 2012调试器,并且发现我的productViewModelList参数不包含我希望我的视图传递给我的[HTTPPOST] Edit操作的所有值。我不明白为什么。请参阅下面代码示例中的注释,了解我插入断点的位置,并检查了productViewModelList的值。
为productViewModelList提供以下值:
BrandId = 0, BrandName =“6”, BrandSelectListItem = null, ID = 5, 名字=“拐杖”, 价格= 10.0
null
。我需要访问DropDownList的Selected项目。以下是我的代码中的一些类。
public class MedicalProductController : Controller
{
private MvcMedicalStoreDb _db = new MvcMedicalStoreDb();
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(IEnumerable<MedicalProductViewModel> productViewModelList)
{
// I have a breakpoint inserted here, and check productViewModelList with debugger.
var modelList = GetMedicalProductList(productViewModelList);
if (ModelState.IsValid)
{
foreach (var model in modelList)
_db.Entry(model).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(productViewModelList);
}
}
public class MedicalProductMapper
{
public IEnumerable<MedicalProductViewModel> MapMedicalProductViewModel(IEnumerable<MedicalProduct> productList, IEnumerable<Brand> brandList)
{
var brandSelectListItem = brandList.Select(b => new SelectListItem()
{
Text = b.Name,
Value = b.ID.ToString()
});
var viewModelList = productList.Select(p => new MedicalProductViewModel()
{
BrandID = p.BrandID,
BrandName = brandList.SingleOrDefault(b => b.ID == p.BrandID).Name,
BrandSelectListItem = brandSelectListItem,
ID = p.ID,
Price = p.Price,
Name = p.Name
});
return viewModelList;
}
public IEnumerable<MedicalProduct> MapMedicalProductList(IEnumerable<MedicalProductViewModel> viewModelList)
{
var modelList = viewModelList.ToArray().Select( viewModel => new MedicalProduct()
{
Name = viewModel.Name,
Price = viewModel.Price,
BrandID = Convert.ToInt32(viewModel.BrandSelectListItem.Select(b => b.Value.ToString()))
});
return modelList;
}
}
@model IEnumerable<MvcMedicalStore.Models.MedicalProductViewModel>
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>MedicalProduct</legend>
@Html.EditorFor(m => m)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
(这是在Edit.cshtml目录的子目录中。)
@model MvcMedicalStore.Models.MedicalProductViewModel
@Html.HiddenFor(item => Model.ID)
<div class="editor-label">
@Html.LabelFor(item => Model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Name)
@Html.ValidationMessageFor(item => Model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(item => Model.Price)
@Html.ValidationMessageFor(item => Model.Price)
</div>
<div class="editor-label">
@Html.LabelFor(item => Model.BrandName)
</div>
<div class="editor-field">
@Html.DropDownListFor(item => Model.BrandName, Model.BrandSelectListItem)
@Html.ValidationMessageFor(item => Model.BrandName)
</div>
public class Brand
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(30)]
public string Name { get; set; }
}
public class MedicalProduct
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
// is a foreign key
public int BrandID { get; set; }
}
public class MedicalProductViewModel
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
public int BrandID { get; set; }
[DisplayFormat(NullDisplayText="[Generic]")]
public string BrandName { get; set; }
public IEnumerable<SelectListItem> BrandSelectListItem { get; set; }
}
答案 0 :(得分:0)
您没有BrandID
的表单元素,因此当模型绑定器将表单POST转换为模型时,它将使用int
的默认值,即0. em> do 有BrandName
的表单元素:
@Html.DropDownListFor(item => Model.BrandName, Model.BrandSelectListItem)
这可能是(取决于BrandSelectListItem
的定义,并基于您描述的观察到的行为)创建select
元素,option
元素使用可用的BrandName
元素BrandID
1}}值作为文本,可用的select
值作为值。当HTTP POST中包含BrandID
元素时,所选值将是发布的值。因此,您将获得所选的BrandName
,但会将其绑定到@Html.DropDownListFor(item => Model.BrandID, Model.BrandSelectListItem)
的值,方法是将其绑定到模型上的该属性。
这听起来像你真正想要的是:
BrandId = 6, BrandName = "", BrandSelectListItem = null, ID = 5, Name = "Crutch", Price = 10.0
然后会给你:
BrandName
您仍然没有BrandName
值,但在这种情况下您真的需要一个吗?这是重复的数据。该模型可以动态确定已知BrandID
中的BrandName
。因此BrandName
不需要是模型的读/写属性,它只能是一个只读属性,它根据模型的BrandID
获取public string BrandName
{
get
{
var brandName = GetBrandName(BrandID);
return brandName;
}
}
。它可能很简单:
GetBrandName
在这种情况下,您将实现BrandID
以从数据存储中获取值。或者如果它足够清晰和简洁,那就完成整个事情,这取决于你。您还可以将值缓存在类级别的私有变量中,以便只需要获取一次。 (只需确保清除该变量或在{{1}}更改时随时重新获取它。)
你可以保持两个属性不变,但是你要负责确保它们在对象的生命周期内保持同步,包括它在UI中花费的时间。只要您在两个地方记录了相同的信息,您就有责任保持同步。这从来都不好玩。在这种情况下,您需要在视图中使用两个元素(第二个可能是隐藏的表单字段,或者可能是一个样式为隐藏的下拉列表),并且您必须编写一些JavaScript以便随时更新一个另一个改变了。