ASP.net MVC - 可空属性自定义属性错误信息 [英] ASP.net MVC - Custom attribute error message with nullable properties

查看:118
本文介绍了ASP.net MVC - 可空属性自定义属性错误信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我的视图模型的属性,可以接受整型和空的值:

I am having a property in my View Model which can accept integer and nullable values:

    [Display(Name = "Code Postal")]
    public int? CodePostal { get; set; }

当我在字符串值类型,怎么能比显示另一条消息默认的:

When I type in string values, how can display another message than the default one:

The field Code Postal must be a number.

感谢

推荐答案

这是有点令人失望看到有关我们要做的工作量时,我们所希望的是通过默认的模型绑定进行的隐含验证自定义错误消息。原因是 DefaultModelBinder 隐藏了一些重要的方法为私有尤其是 GetValueInvalidResource GetValueRequiredResource 。我希望他们会照顾这个未来。

It's little disappointing to see about the amount of work we have to do when all we want is a custom error message for the implicit validations done by the default model binder. The reason is the DefaultModelBinder hides some important methods as private especially the GetValueInvalidResource and GetValueRequiredResource. I hope they will take care of this in future.

我是想给避免为每个类型创建模型活页夹问题的通用的解决方案。

I was trying to give a generic solution for the problem avoiding to create model binders for every type.

老实说,我还没有测试以下实施在所有情况下(例如绑定时的集合),但在基层一样。

因此​​,这里是办法。

So here is the approach.

我们有两个自定义属性,有助于通过自定义错误消息为我们的自定义模型粘合剂。我们可以有一个基类,但是这很好。

We have two custom attributes that helps to pass custom error message for our custom model binder. We could have a base class but that's fine.

public class PropertyValueInvalidAttribute: Attribute
{
    public string ErrorMessage { get; set; }

    public PropertyValueInvalid(string errorMessage)
    {
        ErrorMessage = errorMessage;
    }
}

public class PropertyValueRequiredAttribute: Attribute
{
    public string ErrorMessage { get; set; }

    public PropertyValueRequired(string errorMessage)
    {
        ErrorMessage = errorMessage;
    }
}

下面是模型绑定,这是通用的,独立的类型和需要自定义错误消息必需的和无效的验证照顾。

Here is the model binder this is generic and independent of types and takes care of customizing error messages for both required and invalid validations.

public class ExtendedModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);

        if (propertyDescriptor.Attributes.OfType<PropertyValueInvalidAttribute>().Any())
        {
            var attr = propertyDescriptor.Attributes.OfType<PropertyValueInvalidAttribute>().First();

            foreach (ModelError error in bindingContext.ModelState[propertyDescriptor.Name]
            .Errors.Where(err => String.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null)
            .ToList())
            {
                for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)
                {
                    if (exception is FormatException)
                    {
                        bindingContext.ModelState[propertyDescriptor.Name].Errors.Remove(error);
                        bindingContext.ModelState[propertyDescriptor.Name].Errors.Add(attr.ErrorMessage);
                        break;
                    }
                }
            }
        }
    }

    protected override void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        if (propertyDescriptor.Attributes.OfType<PropertyValueRequiredAttribute>().Any())
        {
            var attr = propertyDescriptor.Attributes.OfType<PropertyValueRequiredAttribute>().First();

            var isTypeAllowsNullValue = (!propertyDescriptor.PropertyType.IsValueType || Nullable.GetUnderlyingType(propertyDescriptor.PropertyType) != null);

            if (value == null && !isTypeAllowsNullValue)
            {
                bindingContext.ModelState[propertyDescriptor.Name].Errors.Clear();
                bindingContext.ModelState.AddModelError(propertyDescriptor.Name, attr.ErrorMessage);
            }
        }

        base.OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, value);
    }
}

我们正在覆盖 OnPropertyValidated 方法只覆盖由默认的模型绑定抛出的隐含所需的错误消息,我们正在重写的SetProperty 只是用我们自己的消息时类型无效。

We are overriding the OnPropertyValidated method just to override the implicit required error message thrown by the default model binder, and we are overriding the SetProperty just to use our own message when the type is not valid.

设置我们的定制绑定在Global.asax.cs中的默认

Set our custom binder as the default in Global.asax.cs

ModelBinders.Binders.DefaultBinder = new ExtendedModelBinder();

和可以装饰你的属性这样的..

And you can decorate your properties like this..

[PropertyValueRequired("this field is required")]
[PropertyValueInvalid("type is invalid")]
[Display(Name = "Code Postal")]
public int? CodePostal { get; set; }

这篇关于ASP.net MVC - 可空属性自定义属性错误信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆