MVC 2 模型验证期间 IDataErrorInfo 是否被忽略?

发布于 2024-08-12 06:20:01 字数 71 浏览 6 评论 0原文

我目前将我的项目迁移到 MVC 2,并且在使用默认模型绑定和验证时 IDataErrorInfo 似乎不起作用。是不是被剪掉了?

I currently migrated my project to MVC 2 and IDataErrorInfo doesn't seem to work when using default model binding and validation. Is it cut out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不知所踪 2024-08-19 06:20:01

摘要

我将此错误发布到 MVC 2 问题跟踪器: http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=4891

它将在下一个预览版本中解决。


MVC 1.0 中的 DefaultModelBinder:

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
    IDataErrorInfo model = bindingContext.Model as IDataErrorInfo;
    if (model != null)
    {
        string str = model[propertyDescriptor.Name];
        if (!string.IsNullOrEmpty(str))
        {
            string key = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
            bindingContext.ModelState.AddModelError(key, str);
        }
    }
}

MVC 2.0 beta 中的 DefaultModelBinder:

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
    ModelMetadata metadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
    metadata.Model = value;
    string prefix = CreateSubPropertyName(bindingContext.ModelName, metadata.PropertyName);
    foreach (ModelValidator validator in metadata.GetValidators(controllerContext))
    {
        foreach (ModelValidationResult result in validator.Validate(bindingContext.Model))
        {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(prefix, result.MemberName), result.Message);
        }
    }
    if ((bindingContext.ModelState.IsValidField(prefix) && (value == null)) && !TypeHelpers.TypeAllowsNullValue(propertyDescriptor.PropertyType))
    {
        bindingContext.ModelState.AddModelError(prefix, GetValueRequiredResource(controllerContext));
    }
}

它不使用 IDataErrorInfo this[string columnName] 属性...似乎是一个错误,因为 DefaultModelBinder 仍然使用 Error 属性。至少这是不一致的。

编辑

我使用了 Reflector 并注意到 DataErrorInfoPropertyModelValidator 似乎没有被使用,所以我创建了自己的类:

public class DataErrorInfoModelPropertyValidatorProvider : ModelValidatorProvider
{
    // Methods
    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
    {
        if (metadata == null)
        {
            throw new ArgumentNullException("metadata");
        }
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var validators = new List<ModelValidator>();
        validators.Add(new DataErrorInfoPropertyModelValidator(metadata, context));
        return validators;
    }

    internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator
    {
        // Methods
        public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
            : base(metadata, controllerContext)
        {
        }

        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            if (container != null)
            {
                IDataErrorInfo info = container as IDataErrorInfo;
                if (info != null)
                {
                    string str = info[Metadata.PropertyName];
                    if (!string.IsNullOrEmpty(str))
                    {
                        ModelValidationResult[] resultArray = new ModelValidationResult[1];
                        ModelValidationResult result = new ModelValidationResult();
                        result.Message = str;
                        resultArray[0] = result;
                        return resultArray;
                    }
                }
            }
            return Enumerable.Empty<ModelValidationResult>();
        }
    }
}

然后我使用了:

ModelValidatorProviders.Providers.Add(new DataErrorInfoModelPropertyValidatorProvider());

并且它有效:)这只是临时解决方案。必须在最终的 MVC 2 中进行更正。

编辑

我还在 中将 if (base.Metadata.Model != null) 更改为 if (container != null) DataErrorInfoPropertyModelValidator 的 >Validate() 方法。

SUMMARY

I posted this error to MVC 2 issue tracker: http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=4891

It will be resolved in next preview release.


DefaultModelBinder in MVC 1.0:

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
    IDataErrorInfo model = bindingContext.Model as IDataErrorInfo;
    if (model != null)
    {
        string str = model[propertyDescriptor.Name];
        if (!string.IsNullOrEmpty(str))
        {
            string key = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
            bindingContext.ModelState.AddModelError(key, str);
        }
    }
}

DefaultModelBinder in MVC 2.0 beta:

protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
    ModelMetadata metadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
    metadata.Model = value;
    string prefix = CreateSubPropertyName(bindingContext.ModelName, metadata.PropertyName);
    foreach (ModelValidator validator in metadata.GetValidators(controllerContext))
    {
        foreach (ModelValidationResult result in validator.Validate(bindingContext.Model))
        {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(prefix, result.MemberName), result.Message);
        }
    }
    if ((bindingContext.ModelState.IsValidField(prefix) && (value == null)) && !TypeHelpers.TypeAllowsNullValue(propertyDescriptor.PropertyType))
    {
        bindingContext.ModelState.AddModelError(prefix, GetValueRequiredResource(controllerContext));
    }
}

It doesn't use IDataErrorInfo this[string columnName] property... Seems like a bug, because DefaultModelBinder still uses Error property. It is inconsistency at least.

EDIT

I used reflector and noticed that DataErrorInfoPropertyModelValidator doesn't seem to be used, so I created my own class:

public class DataErrorInfoModelPropertyValidatorProvider : ModelValidatorProvider
{
    // Methods
    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
    {
        if (metadata == null)
        {
            throw new ArgumentNullException("metadata");
        }
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var validators = new List<ModelValidator>();
        validators.Add(new DataErrorInfoPropertyModelValidator(metadata, context));
        return validators;
    }

    internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator
    {
        // Methods
        public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
            : base(metadata, controllerContext)
        {
        }

        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            if (container != null)
            {
                IDataErrorInfo info = container as IDataErrorInfo;
                if (info != null)
                {
                    string str = info[Metadata.PropertyName];
                    if (!string.IsNullOrEmpty(str))
                    {
                        ModelValidationResult[] resultArray = new ModelValidationResult[1];
                        ModelValidationResult result = new ModelValidationResult();
                        result.Message = str;
                        resultArray[0] = result;
                        return resultArray;
                    }
                }
            }
            return Enumerable.Empty<ModelValidationResult>();
        }
    }
}

Then I used:

ModelValidatorProviders.Providers.Add(new DataErrorInfoModelPropertyValidatorProvider());

And it works:) This is just temporary solution. Will have to be corrected in final MVC 2.

EDIT

I also changed if (base.Metadata.Model != null) to if (container != null) in Validate() method of DataErrorInfoPropertyModelValidator.

凡尘雨 2024-08-19 06:20:01

它肯定在 MVC 2 Preview 2 中。请查看 DefaultModelBinder.OnPropertyValidatingOnModelUpdated

It's certainly in MVC 2 Preview 2. Look at DefaultModelBinder.OnPropertyValidating and OnModelUpdated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文