This is my Model class
public class Model
{
[DataType(DataType.DateTime, ErrorMessage = "My error message")]
public DateTime Day { get; set; }
}
When I try to input incorrect value for example "notdate" i got the error
"The value 'notdate' is not valid for Day." instead of my specified ErrorMessage "My error message".
I use ASP.NET MVC 3.0 beta. This is a bug?
There are a few things to note about the behavior you are describing.
First, you are receiving this error because an exception is being thrown when attempting to assign the string value 'notdate' to a DateTime field. When this happens, any validation messages that may have been associated with the field will be overwritten with the generic message: The value '{0}' is not valid for {1}.
Second,the base DataTypeAttribute doesn't actually perform any validation on the field. Using Reflector, you will see that the DataTypeAttribute.IsValid() method is declared as follows:
public override bool IsValid(object value)
{
return true;
}
Hope this helps.
No, this is the default functionality of the existing model binder.
The DataType has nothing to do with basic model binding and won't override basic model binding errors.
Related
I am trying to replace the default validation messages in MVC3 that are displayed when you fail to fill in a required field or fill in an invalid value. I am only addressing server-side validation in this question. My custom message for invalid value is working, but the one for missing required field won't apply.
This is what I have done:
Added an ASP.NET folder called "App_GlobalResources" to the web project, and in that folder I placed a resources file called "DefaultMessages.resx", containing the following keys and values:
PropertyValueInvalid: The value you input is invalid
PropertyValueRequired: This field is required
(These are not the actual messages I will be using; they will be in a different language, which is my primary reason for needing to replace the default ones.)
Registered the resource file with the DefaultModelBinder in Global.asax.cs like this (note I am using Ninject for dependency injection):
public class MvcApplication : NinjectHttpApplication
{
...
protected override void OnApplicationStarted()
{
...
DefaultModelBinder.ResourceClassKey = "DefaultMessages";
...
}
...
}
In my model I have a DateTime property called ExpirationDate. Since DateTime is non-nullable, the property is implicitly required. PropertyValueInvalid works; my custom message is rendered in the form after I submit with an invalid value in the ExpirationDate field, such as 30.02.2014. But if I leave the field empty and submit, I only get the default "The ExpirationDate field is required".
What am I missing here? Is PropertyValueRequired not the right name? Or does it not apply to implicitly required properties? I also tried adding an explicit Required attribute in the Model, like this:
[Required]
public DateTime ExpirationDate{ get; set; }
But that makes no difference. What does work is adding a custom error message to the attribute, for example like this:
[Required(ErrorMessage = "We need a date here!")]
public DateTime ExpirationDate{ get; set; }
But I don't want to do that for all the required properties that typically just need a generic message. (I know I could reference the generic message in the resource file in the Required attribute instead of stating the message directly, but that still adds clutter to the Model that should not be necessary.)
For the date validation you need to handle the localization of : FieldMustBeDate actually what you are doing is correct but in order to handle all messages you need to have the following messages localized just in case:
FieldMustBeDate
FieldMustBeNumeric
PropertyValueInvalid
PropertyValueRequired
I'm using ASP.NET MVC 3 with Fluent Validation. I'd like all my error messages to be worded and formatted the same, whether they are validation error messages or model binding error messages.
Let's say I have the following view-model:
[Validator(typeof(PersonValidator))]
public class Person
{
[ScaffoldColumn(false)] public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
To validate this using Fluent Validation, I might use something like this:
public class EditorValidator : AbstractValidator<EditorModel>
{
public EditorValidator()
{
RuleFor(model => model.Month.Value).InclusiveBetween(0, 120)
}
}
If the user enters "abc" for Age, this causes a model binding error, not a validation error. This is because "abc" is not an int. The system never even gets to the point of asking whether "abc" is between 0 and 120, because "abc" cannot be stored in Age.
This is fine and makes sense. The problem is that the resulting error message is:
The field Age must be a number.
I'd like the message to be formatted and worded like other error message produced by Fluent Validation. In this case, I would like:
'Age' must be a number.
I realize this is only a subtle difference, but I'd like to have control of model binding error messages.
How can I customize the model binding error messages to match the error messages used by Fluent Validation?
I'm not sure if there's another way to do this, but I use Data Annotations Extensions, also available via NuGet (Install-Package DataAnnotationsExtensions.MVC3) for this exact type of thing. This package will give you an IntegerAttribute, and from there you can specify an error message like so:
[Integer(ErrorMessage = "'Age' must be a number.")]
public int Age { get; set; }
Take a look at my answer here:
How to change 'data-val-number' message validation in MVC while it is generated by #Html helper
Actually, it's a very common question that you asked, so you should've googled the stackoverflow prior to posting.
I am trying to realize valition on data type. I have used DataAnnotations, but for data type it's not showing customized message
for example when I' am trying enter string data into int typed field. How I can customize messages in this case?
If I had to guess, you sound like you want a custom message to display when validating one or more fields in your model. You can subclass the DataAnnotations.ValidationAttribute class and override the IsValid(object) method and finally setting a custom ErrorMessage value (where ErrorMessage already belongs to the ValidationAttribute class)
public class SuperDuperValidator : ValidationAttribute
{
public override bool IsValid(object value)
{
bool valid = false;
// do your validation logic here
return valid;
}
}
Finally, decorate your model property with the attribute
public class MyClass
{
[SuperDuperValidator(ErrorMessage="Something is wrong with MyInt")]
public int MyInt { get; set; }
}
If you're using out-of-the-box MVC3, this should be all you need to propertly validate a model (though your model will probably differ/have more properties, etc) So, in your [HttpPost] controller action, MVC will automagically bind MyClass and you will be able to use ModelState.IsValid to determine whether or not the posted data is, in fact, valid.
Pavel,
The DataAnnotations DataType attribute does not affect validation. It's used to decide how your input is rendered. In such a case, David's solution above works.
However, if you want to use only the built-in validation attributes, you probably need to use the Range attribute like this:
[Range(0, 10, ErrorMessage="Please enter a number between 0 and 10")]
public int MyInt { get ; set ;}
(Of course, you should really be using the ErrorMessageResourceName/Type parameters and extract out hard-coded error message strings into resx files.)
Make sure to let MVC know where to render your error message:
<%= Html.ValidationMessageFor(m => m.MyInt) %>
Or you can just use EditorForModel and it will set it up correctly.
I don't think this has been answered because I have the same issue.
If you have a Model with a property of type int and the user types in a string of "asd" then the MVC3 framework binding/validation steps in and results in your view displaying "The value 'asd' is not valid for <model property name or DisplayName here>".
To me the poster is asking can this message that the MVC3 framework is outputting be customized?
I'd like to know too. Whilst the message is not too bad if you label your field something that easily indicates an number is expected you might still want to include additional reasons so it says something like:
"The value 'asd' is not valid for <fieldname>; must be a positive whole number."
So that the user is not entering value after value and getting different error messages each time.
how can I use a Required Validation in a property Prop2 only if the Prop1 is true?
Ex:
public bool Prop1 { get; set; }
[Required] // I need this validation only if the Prop1 is true.
public string Prop2 { get; set; }
Any idea? I need on client and server side.
Thanks
You could use MVC FoolProof Validation framework
It has useful feature like
[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]
[Is]
[EqualTo]
[NotEqualTo]
[GreaterThan]
[LessThan]
[GreaterThanOrEqualTo]
[LessThanOrEqualTo]
Hope this would help you!
There are two parts to this. First, you have to write a required attribute that's only required if the other property meets your criteria.
You'd have to do something like:
public class RequiredComparerAttribute : RequiredAttribute
{
public OtherProperty { get; set; }
public override bool IsValid(object value)
{
// TODO: use reflection to validate other property as PropertyInfo
// or validate it's value after it is decided to be valid
foreach (ValidationAttribute va in property
.GetCustomAttributes(typeof(ValidationAttribute), true)
.OfType<ValidationAttribute>())
{
if (!va.IsValid(value))
{
return false; // not required
}
}
return true; // required
}
}
Then, in Application_Start in the Global.asax, you'll have to register the validator, which you can just reuse the RequiredAttribute's validator:
DataAnnotationsModelValidatorProvider
.RegisterAdapter(typeof(RequiredComparerAttribute),
typeof(RequiredAttributeAdapter));
If you want to add your own validator, you'll have to write a custom validator. Phil Haack has an example on his blog: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Edit: Take a look at CompareAttribute in .NET Reflector for a sense of how to get the value of the OtherProperty. CompareAttribute also implements IClientValidatable to provide those validation rules needed on the client side.
I don't think CompareAttribute will work for you because you have to validate that a value is required based on content of another property, not compare the equality of two properties.
Edit2: What does the Validation provider do?
It adds rules to the form and provides messages for those rules. You can see exactly how the RequiredAttributeAdapter does this by downloading the MVC 3 source. To understand what it does on the client side, you can open the MVC 3 page in Google Chrome, hit CTRL+SHIFT+J to bring up a developer tools window and enter:
$('form:first').data().unobtrusiveValidation.options
The rules object inside options specifies how to validate each item and the message object specifies the error message that will be displayed for each validation error.
Edit3: Full example
Since answering this question, I've written a blog post with a full example of creating a custom attribute on the client (unobtrusive validation) and server. The blog post is here. This example is for a 'contains' attribute, but it should be pretty easy to modify to become a required comparison.
You can write a custom validator do to this job.
Let me know if you need help to do it.
Is it possible in ASP.NET MVC for a CustomValidationAttribute on one field to execute only if a different CustomValidationAttribute validates a different field.
My view needs to contain separate date and time fields. I have separate custom validation attributes for both. But is it possible that the time validation attribute is checked only when date validation attribute validates to true ?
Thanks.
time validation attribute is checked
only when date validation attribute
validates to true ?
This statement means custom validation. Yes, you can do this. You Could Define custom validation attribute that takes other field's name as parameter. Then, in overrided Validate() method, you could get PropertyInfo for that other field by the name, then get validation attributes and validate them. After getting the result, you could decide whether to do validation on first field or not. Brad Wilson had great post on mvcConf about validation
By the way, you could also implement IClientValidatable to wrap up client side validation
This is the very very sample code and it needs some argument checking and error handling, etc. But i think idea is clear
public class OtherFieldDependentCustomValidationAttribute : ValidationAttribute
{
public readonly string _fieldName;
public OtherFieldDependentCustomValidationAttribute(string otherFieldName)
{
_fieldName = otherFieldName;
}
protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext)
{
//Get PropertyInfo For The Other Field
PropertyInfo otherProperty = validationContext.ObjectType.GetProperty(_fieldName);
//Get ValidationAttribute of that property. the OtherFieldDependentCustomValidationAttribute is sample, it can be replaced by other validation attribute
OtherFieldDependentCustomValidationAttribute attribute = (OtherFieldDependentCustomValidationAttribute)(otherProperty.GetCustomAttributes(typeof(OtherFieldDependentCustomValidationAttribute), false))[0];
if (attribute.IsValid(otherProperty.GetValue(validationContext.ObjectInstance, null), validationContext) == ValidationResult.Success)
{
//Other Field Is valid, do some custom validation on current field
//custom validation....
throw new ValidationException("Other is valid, but this is not");
}
else
{
//Other Field Is Invalid, do not validate current one
return ValidationResult.Success;
}
}
}