如何解决绑定到模型的MVC DropDownList值不受限制
|| DropDownLists可能是我最不喜欢使用MVC框架的部分。我的表单中有几个下拉菜单,需要将其选择的值传递给接受模型作为其参数的ActionResult。 标记如下所示:<div class=\"editor-label\">
@Html.LabelFor(model => model.FileType)
</div>
<div class=\"editor-field\">
@Html.DropDownListFor(model => model.FileType.Variety,(SelectList)ViewBag.FileTypes)
</div>
<div class=\"editor-label\">
@Html.LabelFor(model => model.Status)
</div>
<div class=\"editor-field\">
@Html.DropDownListFor(model => model.Status.Status,(SelectList)ViewBag.Status)
</div>
我的控制器动作如下所示:
[HttpPost]
public ActionResult Create(int reviewid,ReviewedFile file)
{
if (ModelState.IsValid)
{
UpdateModel(file);
}
//repository.Add(file);
return RedirectToAction(\"Files\",\"Reviews\",new { reviewid = reviewid,id = file.ReviewedFileId });
}
除了下拉列表中的值被发布为null之外,这应该很好。当我进一步查看ModelState错误时,发现原因是:
从类型转换参数
\'System.String \'键入
\'PeerCodeReview.Models.OutcomeStatus \'
失败,因为没有类型转换器可以
在这些类型之间转换。
应该不难,但确实如此。所以问题是;为了正确绑定模型属性,我需要怎么做?
顺便说一句,我知道我可以传递一个FormCollection对象,但这意味着更改我的单元测试的重要部分,这些部分当前需要强类型模型参数。
解决方法
尝试以下方法:
<div class=\"editor-label\">
@Html.LabelFor(model => model.FileType)
</div>
<div class=\"editor-field\">
@Html.DropDownListFor(model => model.FileType.Id,(SelectList)ViewBag.FileTypes)
</div>
<div class=\"editor-label\">
@Html.LabelFor(model => model.Status)
</div>
<div class=\"editor-field\">
@Html.DropDownListFor(model => model.Status.Id,(SelectList)ViewBag.Status)
</div>
,您需要为绑定到下拉列表的两个属性创建并注册自定义模型绑定程序。
这是我为此目的而建立的模型资料夹的代码:
public class LookupModelBinder<TModel> : DefaultModelBinder
where TModel : class
{
private string _key;
public LookupModelBinder(string key = null)
{
_key = key ?? typeof(TModel).Name;
}
public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
{
var dbSession = ((IControllerWithSession)controllerContext.Controller).DbSession;
var modelName = bindingContext.ModelName;
TModel model = null;
ValueProviderResult vpResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (vpResult != null)
{
bindingContext.ModelState.SetModelValue(modelName,vpResult);
var id = (int?)vpResult.ConvertTo(typeof(int));
model = id == null ? null : dbSession.Get<TModel>(id.Value);
}
if (model == null)
{
ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(bindingContext.ModelMetadata,controllerContext).Where(v => v.IsRequired).FirstOrDefault();
if (requiredValidator != null)
{
foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model))
{
bindingContext.ModelState.AddModelError(modelName,validationResult.Message);
}
}
}
return model;
}
}
“ 4”是下拉框应绑定到的属性的类型。在我的应用程序中,下拉框提供了数据库中对象的ID,因此此模型绑定程序获取该ID,从数据库中检索正确的实体,然后返回该实体。您可能会采用其他方法将下拉列表中给出的字符串转换为模型的正确实体。
您还需要在Global.asax
中注册模型资料夹。
binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>();
假定下拉列表控件的名称与类型名称相同。如果没有,您可以将密钥传递给模型绑定器。
binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>(\"ControlName\");
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。