加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – DataAnnotationsModelBinder如何使用自定义ViewModel?

发布时间:2020-05-23 21:52:01 所属栏目:asp.Net 来源:互联网
导读:我正在尝试使用 DataAnnotationsModelBinder,以便在ASP.NET MVC中使用数据注释进行服务器端验证. 只要我的ViewModel只是一个具有直接属性的简单类,一切都可以正常工作 public class Foo{ public int Bar {get;set;}} 但是,DataAnnotationsModelBinder在尝试使

我正在尝试使用 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);
            }
        /

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读