ASP.NET MVC - Custom validation message for value types

前端 未结 7 1891
粉色の甜心
粉色の甜心 2020-11-30 02:46

When I use UpdateModel or TryUpdateModel, the MVC framework is smart enough to know if you are trying to pass in a null into a value type (e.g. the user forgets to fill out

相关标签:
7条回答
  • yes, there is a way, you must use System.ComponentModel.DataAnnotations in combination with xVal and you are going to be able to set validation rules and messages (u can even use resource files for localization) for each of your property using Attributes
    look here http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/

    0 讨论(0)
  • 2020-11-30 03:05

    Look up ModelState.AddError.

    0 讨论(0)
  • 2020-11-30 03:08

    In ASP.NET MVC 1, I met this problem too.

    In my project, there is a model or business object named "Entry", and its primary key EntryId is int? type, and the value of EntryId can be allowd to input by users.

    So the problem is, when the field is blank or zero or some integer value that has existed, the custom error messages can be shown well, but if the value is some non-integer value like "a", i can not find a way to use the custom message to replace the default message like "The value 'a' is invalid".

    when i track the error message in ModelState, i found when the value is non-integer, there will be two errors related to EntryId, and the first item's error message is blank...

    Now i have to use such an ugly code to hack the problem.

    if (ModelState["EntryId"].Errors.Count > 1)
    {
        ModelState["EntryId"].Errors.Clear(); //should not use ModelState["EntryId"].remove();
        ModelState.AddModelError("EntryId", "必须为大于0的整数"); //必须为大于0的整数 means "it should be an integer value and great than 0"
    }  
    

    but this makes controller fat, hope there is a real solution to solve it.

    0 讨论(0)
  • 2020-11-30 03:09

    how about this?

    [RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
                       ErrorMessage = "Characters are not allowed.")]
    

    That should allow you to tag properties with specific error messages for whatever MVC validators you want to use...

    0 讨论(0)
  • 2020-11-30 03:11

    Make your own ModelBinder by extending DefaultModelBinder:

    public class LocalizationModelBinder : DefaultModelBinder
    

    Override SetProperty:

            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    
            foreach (var error in bindingContext.ModelState[propertyDescriptor.Name].Errors.
                Where(e => IsFormatException(e.Exception)))
            {
                if (propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)] != null)
                {
                    string errorMessage =
                        ((TypeErrorMessageAttribute)propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)]).GetErrorMessage();
                    bindingContext.ModelState[propertyDescriptor.Name].Errors.Remove(error);
                    bindingContext.ModelState[propertyDescriptor.Name].Errors.Add(errorMessage);
                    break;
                }
            }
    

    Add the function bool IsFormatException(Exception e) to check if an Exception is a FormatException:

    if (e == null)
                return false;
            else if (e is FormatException)
                return true;
            else
                return IsFormatException(e.InnerException);
    

    Create an Attribute class:

    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
    public class TypeErrorMessageAttribute : Attribute
    {
        public string ErrorMessage { get; set; }
        public string ErrorMessageResourceName { get; set; }
        public Type ErrorMessageResourceType { get; set; }
    
        public TypeErrorMessageAttribute()
        {
        }
    
        public string GetErrorMessage()
        {
            PropertyInfo prop = ErrorMessageResourceType.GetProperty(ErrorMessageResourceName);
            return prop.GetValue(null, null).ToString();
        }
    }
    

    Add the attribute to the property you wish to validate:

    [TypeErrorMessage(ErrorMessageResourceName = "IsGoodType", ErrorMessageResourceType = typeof(AddLang))]
        public bool IsGood { get; set; }
    

    AddLang is a resx file and IsGoodType is the name of the resource.

    And finally add this into Global.asax.cs Application_Start:

    ModelBinders.Binders.DefaultBinder = new LocalizationModelBinder();
    

    Cheers!

    0 讨论(0)
  • 2020-11-30 03:12

    With the DefaultModelBinder it is possible to override the default required error message but unfortunately it would apply globally which IMHO renders it completely useless. But in case you decide to do it here's how:

    1. Add the App_GlobalResources folder to your ASP.NET site
    2. Add a resources file called Messages.resx
    3. Inside the resources file declare a new string resource with the key PropertyValueRequired and some value
    4. In Application_Start add the following line:

      DefaultModelBinder.ResourceClassKey = "Messages";
      

    As you can see there's no link between the model property you are validating and the error message.

    In conclusion it is better to write custom validation logic to handle this scenario. One way would be to use a nullable type (System.Nullable<TValueType>) and then:

    if (model.MyProperty == null || 
        /** Haven't tested if this condition is necessary **/ 
        !model.MyProperty.HasValue)
    {
        ModelState.AddModelError("MyProperty", "MyProperty is required");
    }
    
    0 讨论(0)
提交回复
热议问题