asp.net-mvc – DataAnnotationsModelBinder如何使用自定义ViewM
我正在尝试使用
DataAnnotationsModelBinder,以便在ASP.NET MVC中使用数据注释进行服务器端验证.
只要我的ViewModel只是一个具有直接属性的简单类,一切都可以正常工作 public class Foo { public int Bar {get;set;} } 但是,DataAnnotationsModelBinder在尝试使用复杂的ViewModel时会导致NullReferenceException,例如 public class Foo { public class Baz { public int Bar {get;set;} } public Baz MyBazProperty {get;set;} } 对于渲染多个LINQ实体的视图来说,这是一个很大的问题,因为我更喜欢使用包含多个LINQ实体而不是无类型ViewData数组的自定义ViewModel. DefaultModelBinder没有这个问题,所以它似乎是DataAnnotationsModelBinder中的一个错误.这有什么解决方法吗? 编辑:一种可能的解决方法当然是在ViewModel类中公开子对象的属性,如下所示: public class Foo { private Baz myBazInstance; [Required] public string ExposedBar { get { return MyBaz.Bar; } set { MyBaz.Bar = value; } } public Baz MyBaz { get { return myBazInstance ?? (myBazInstance = new Baz()); } set { myBazInstance = value; } } #region Nested type: Baz public class Baz { [Required] public string Bar { get; set; } } #endregion } #endregion 但我宁愿不必编写所有这些额外的代码. DefaultModelBinder可以正常使用这样的hiearchies,所以我认为DataAnnotationsModelBinder也应该如此. 第二次编辑:看起来这确实是DataAnnotationsModelBinder中的一个错误.但是,希望在下一个ASP.NET MVC框架版本发布之前可以修复它.有关详细信息,请参见this forum thread. 解决方法
我今天遇到了同样的问题.像我自己一样,我没有将我的View直接绑定到我的模型,而是使用一个中间的ViewDataModel类,它包含Model的一个实例以及我想发送给视图的任何参数/配置.
我最终修改了DataAnnotationsModelBinder上的BindProperty来绕过NullReferenceException,我个人不喜欢只有绑定它们才有效(见下面的原因). protected override void BindProperty(ControllerContext controllerContext,ModelBindingContext bindingContext,PropertyDescriptor propertyDescriptor) { string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName,propertyDescriptor.Name); // Only bind properties that are part of the request if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) { var innerContext = new ModelBindingContext() { Model = propertyDescriptor.GetValue(bindingContext.Model),ModelName = fullPropertyKey,ModelState = bindingContext.ModelState,ModelType = propertyDescriptor.PropertyType,ValueProvider = bindingContext.ValueProvider }; IModelBinder binder = Binders.GetBinder(propertyDescriptor.PropertyType); object newPropertyValue = ConvertValue(propertyDescriptor,binder.BindModel(controllerContext,innerContext)); ModelState modelState = bindingContext.ModelState[fullPropertyKey]; if (modelState == null) { var keys = bindingContext.ValueProvider.FindKeysWithPrefix(fullPropertyKey); if (keys != null && keys.Count() > 0) modelState = bindingContext.ModelState[keys.First().Key]; } // Only validate and bind if the property itself has no errors //if (modelState.Errors.Count == 0) { SetProperty(controllerContext,bindingContext,propertyDescriptor,newPropertyValue); if (OnPropertyValidating(controllerContext,newPropertyValue)) { OnPropertyValidated(controllerContext,newPropertyValue); } //} // There was an error getting the value from the binder,which was probably a format // exception (meaning,the data wasn't appropriate for the field) if (modelState.Errors.Count != 0) { foreach (var error in modelState.Errors.Where(err => err.ErrorMessage == "" && err.Exception != null).ToList()) { for (var exception = error.Exception; exception != null; exception = exception.InnerException) { if (exception is FormatException) { string displayName = GetDisplayName(propertyDescriptor); string errorMessage = InvalidValueFormatter(propertyDescriptor,modelState.Value.AttemptedValue,displayName); modelState.Errors.Remove(error); modelState.Errors.Add(errorMessage); break; } } } } } } 我也对它进行了修改,以便它始终绑定属性上的数据,无论它是否有效.这样我就可以将模型传递回视图,而无需将无效属性重置为null. 控制器摘录 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(ProfileViewDataModel model) { FormCollection form = new FormCollection(this.Request.Form); wsPerson service = new wsPerson(); Person newPerson = service.Select(1,-1); if (ModelState.IsValid && TryUpdateModel<IPersonBindable>(newPerson,"Person",form.ToValueProvider())) { //call wsPerson.save(newPerson); } return View(model); //model.Person is always bound no null properties (unless they were null to begin with) } 我的Model类(Person)来自web服务,所以我不能直接将属性放在它们上面,我解决这个问题的方法如下: 嵌套DataAnnotations的示例 [Validation.MetadataType(typeof(PersonValidation))] public partial class Person : IPersonBindable { } //force partial. public class PersonValidation { [Validation.Immutable] public int Id { get; set; } [Validation.Required] public string FirstName { get; set; } [Validation.StringLength(35)] [Validation.Required] public string LastName { get; set; } CategoryItemNullable NearestGeographicRegion { get; set; } } [Validation.MetadataType(typeof(CategoryItemNullableValidation))] public partial class CategoryItemNullable { } public class CategoryItemNullableValidation { [Validation.Required] public string Text { get; set; } [Validation.Range(1,10)] public string Value { get; set; } } 现在,如果我将表单字段绑定到[ViewDataModel.] Person.NearestGeographicRegion.Text& [ViewDataModel.] Person.NearestGeographicRegion.Value ModelState开始正确验证它们,DataAnnotationsModelBinder也正确绑定它们. 这个答案不是决定性的,它是今天下午挠头的产物. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 可以将值或参数传递到用户控件?
- asp.net mvc partialview @ Ajax.ActionLink不起作用
- updatepanel – 更新面板不显示ASP.NET 3.5中的错误
- asp.net-core – “如果从deploy文件夹运行,则需要”库’ho
- asp.net – HtmlGenericControl(“br”)呈现两次
- asp.net-mvc – ASP.NET MVC快速教程
- asp.net – 页面上有多个RequiredFieldValidators,但它们需
- asp.net – 如何在图像上创建图层?
- asp.net-mvc-2 – ASP.NET MVC 2和PRG模式
- asp.net – 对绑定到自定义通用对象列表的GridView进行排序
- asp.net-mvc – 多个字段的远程验证
- asp.net – 在Publish上自动压缩html和css?
- asp.net-mvc – 使用ASP.NET MVC v2 EditorFor和
- asp.net-mvc – 在MVC3中,我应该有独立的“编辑”
- Advanced Architecture for ASP.NET Core Web AP
- asp.net – 网站在解决方案构建后需要很长时间才
- vsdoc文件是否适用于vbscript?
- asp.net-mvc-3 – RavenDb,无法访问文件,文件被锁
- 如何在asp.net中使用ccavenue支付网关
- asp.net – T-SQL中的HTML编码?