override error message (The value 'xxx' is not valid for Age) when input incorrect data type for input field asp.net mvc
After spending a couple of hours looking around, I see no one really has a suitable answer to this. I have found a solution that works for me so I thought I'd post it.
The problem for me was validating a nullable int. When a non valid value was entered by the user, the default message "The value 'dsfd' is not valid for Issue'.
The solution I came up with was to remove the errors from the model state and add my own.
The classes to perform the validation are below:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
public class ValidInteger : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null || value.ToString().Length == 0)
{
return ValidationResult.Success;
}
int i;
return !int.TryParse(value.ToString(), out i) ? new ValidationResult(ErrorMessage) : ValidationResult.Success;
}
}
public class ValidIntegerValidator : DataAnnotationsModelValidator<ValidInteger>
{
public ValidIntegerValidator(ModelMetadata metadata, ControllerContext context, ValidInteger attribute)
: base(metadata, context, attribute)
{
if(!attribute.IsValid(context.HttpContext.Request.Form[attribute.ObjectId]))
{
var propertyName = metadata.PropertyName;
context.Controller.ViewData.ModelState[propertyName].Errors.Clear();
context.Controller.ViewData.ModelState[propertyName].Errors.Add(attribute.ErrorMessage);
}
}
}
Don't forget you'll also need to register the adapter in the global Application_Start()
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(ValidInteger), typeof(ValidIntegerValidator));
And decorate your property with the new attribute
[ValidInteger(ErrorMessage = "Please enter a valid number for issue")]
The response from wechel dated February 27, 12 worked for me, except that I needed to replace the line
if(!attribute.IsValid(context.HttpContext.Request.Form[attribute.ObjectId]))
with
if (!attribute.IsValid(context.HttpContext.Request.Form[metadata.PropertyName]))
I am guessing that the change is needed because I am using MVC4 and the code snippet provided was written in an earlier version of MVC?
You can use DataAnnotations to override the default error messages in MVC, as well as provide your own validation for whatever fields you need to. See the following:
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx
http://www.asp.net/mvc/tutorials/validation-with-the-data-annotation-validators-cs
If you are using EF, you will need to create a MetaData class off the EF generated class and then add the data annotations. The end of the 2nd article covers how to write these classes for entity framework.
In your specific case you will want to do something like:
using System.ComponentModel.DataAnnotations;
public class Person
{
public string FirstName {get;set;}
[Range(0, 110, ErrorMessage = "<your error message>")]
public int Age {get;set;}
}
UPDATE I did forget one thing that is easy to overlook, you need to include the following JS files for the data annotations to be picked up client side without having to do a post:
MicrosoftAjax.js
MicrosfotMvcValidation.js
These should be stock in the Scripts folder of your project (if you are using MVC 2), and you need to include them either on your page or in your master page,
<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcValidation.js") %>" type="text/javascript"></script>
you will also need to include
<% Html.EnableClientValidation(); %>
on the page in question.
The client side validation will not let you submit the form until all fields meet validation requirements, as Kaspars Ozols points out you will still need to call Model.IsValid on your controller.