Custom Validation Attribute ASP.NET MVC - asp.net-mvc

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;
}
}
}

Related

Validate method is ignored when decorating validation attribute for hidden property

I have a C# MVC view model called PersonViewModel that inherits the IValidatableObject. There is a property named ClickCount that is integer type. That property is hidden on an MVC view, but it is used to count user clicking on some another visible view element (html element). The requirement for that hidden property is a positive integer. That means user must clicks the other html element at least 1. If user does not click that other html element, then when he/she submits the form to the server via MVC controller POST action method named Save(), the MVC validation error should be brought back to the view page.
The Validation method is used for validating other properties of my MVC model as well and those validation tasks were ignored because the Validation method was ignored as a whole.
To force the validation, in my view model PersonViewModel, I had decorated the hidden property ClickCount as:
[Range(1, int.MaxValue, ErrorMessage = "The Bell button must be clicked at least 1")]
public int ClickCount { get; set; }
That decorating for that hidden property was wrong because it caused the overriden Validation() method of my MVC model PersonViewModel is ignored or not never hit, the debugged ModelState.IsValid was always true although user does not hit the other html element. So, I had to remove the validation attribute for that hidden property. Instead, I moved the validation logic inside the overridden Validation method.
The the overridden Validation method of my view model also contains validation logic for other model properties, too.
My question: why did the validation attribute for hidden property on the MVC view markup page cause the Validation method to be ignored?
The following was my MVC model that has wrong validation attribute for the hidden property ClickCount:
public class PersonViewModel: IValidatableObject
{
[Range(1, int.MaxValue, ErrorMessage = "The Bell button must be clicked at least 1")]
public int ClickCount { get; set; }
}
#region validation
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
…. // logic to validate properties
}
#endregion
}
The MVC cshtml view with the property ClickCount which is hidden:
#Html.HiddenFor(m => m.ClickCount, null)
My controller POST action method which was always hit with ModelState.IsValid which alwasy true because the overriden Validation() method was ignored.
public ActionResult Save(PersonViewModel model)
{
if(ModelState.IsValid)
{
....
}
}
I appreciate your explanation, ideas.

Is it possible to define strings that aren't allowed for MVC Data Annotations?

Basically, I'm wondering exactly what the title says: Is it possible to define certain strings as not allowed through MVC's Data Annotations?
As an example, say I have a string field: Name and I really don't like the name Ned. So is there a way to set up a Data Annotation that displays an ErrorMessage if a user enters Ned into Name?
Sure you can create a custom attribute to do that. It can quite simply checks against a blacklist of names and return true or false depending on the outcome. Creating a class that inherits from the ValidationAttribute is probably the way to go.
Example
public class NameAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// do your blacklist logic here.
return true;
}
}
Try this Microsoft training course on Custom Validation

asp.net mvc 3 validation on data type

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.

MVC validation of Date using DataAnnotations

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.

Custom Model Binder - How to revalidate

I'm using ASP.NET MVC 2 and want to figure out how to re-trigger the validation on my model after it has been populated using a custom binder.
So, I start with a couple of EF classes which are associated, Booking and Traveller (each booking can have one or more travellers)
Here's the buddy class I'm using to place balidation on Booking:
[MetadataType(typeof(Booking_Validation))]
public partial class Booking {
// partial class compiled with code produced by VS designer
}
[Bind(Include="Name")]
public class Booking_Validation {
[Required(ErrorMessage="Booking name required")]
public string Name { get; set; }
[AtLeastOneTraveller(ErrorMessage="Please enter at least one traveller")]
public EntityCollection<Traveller> Travellers;
}
public class AtLeastOneTraveller : ValidationAttribute {
public override bool IsValid(object value) {
if (value != null)
return ((EntityCollection<Traveller>)value).Count > 0;
return true;
}
}
I use a custom model binder to populate the booking and it's associated travellers, except that ModelState.IsValid seems to be set even before my custom model binder has had a chance to add the travellers to the booking object, even even after doing so, ModelState["Travellers"] still contains the validation error saying there must be at least one traveller attached.
Is there any way to re-trigger validation after the custom model binder has done its thing?
Have you tried the TryValidateModel method on the Controller class?
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryvalidatemodel.aspx
try this:
http://shazwazza.com/post/Custom-MVC-ModelBinder-with-Complex-ModelsObjects-using-built-in-MVC-Validation.aspx
Once you have fixed the error items, you can clear the ModelState using
ModelState.Clear();
and then revalidate using
ModelState.IsValid

Resources