How to find what validator types have failed on a model in ASP.NET MVC 3?
I have some standard validator attributes on some properties in my model class. The HTML form gets posted to my controller, and I can check the ModelState
to see if it's valid, and to see what properties are invalid. This is all fine. (I'm not doing any client-side validation.)
However, some of the time, if the only properties failing validation are ones with the RequiredAttribute
on them, I want to treat the model as valid.
I could use Reflection to check each of the properties that have failed validation, and see if each property has a RequiredAttribute
in its custom attributes, but this seems a little heavy. Is there开发者_开发知识库 some bit of the API I'm unaware of that will tell me the types of the validators that have failed?
Well, a crazy requirement demands a crazy solution! In my controller, I was using
if(this.ModelState.IsValid)...
, but now I can use
if(ValidatorChecker<ModelType>.IsModelStateValid(this.ModelState))...
,
with the following:
internal static class ValidatorChecker<TModel>
{
public static bool IsModelStateValid(ModelStateDictionary modelState)
{
if (modelState.IsValid)
{
return true;
}
int totalErrors = 0, requiredAttributeErrors = 0;
Type modelType = typeof(TModel);
foreach (var key in modelState.Keys)
{
if (modelState[key].Errors.Count > 0)
{
totalErrors += modelState[key].Errors.Count;
Type currentType = modelType;
string[] typeParts = key.Split(
new char[] { '.' },
StringSplitOptions.RemoveEmptyEntries);
int typeIndex = 0;
if (typeParts.Length == 0)
{
continue;
}
else if (typeParts.Length > 1)
{
for (typeIndex = 0; typeIndex < typeParts.Length - 1; typeIndex++)
{
currentType =
currentType.GetProperty(typeParts[typeIndex]).PropertyType;
}
}
PropertyInfo validatedProperty =
currentType.GetProperty(typeParts[typeIndex]);
var requiredValidators =
validatedProperty.GetCustomAttributes(typeof(RequiredAttribute), true);
requiredAttributeErrors += requiredValidators.Length;
}
}
return requiredAttributeErrors == totalErrors;
}
}
The validation occurs as part of the model binder extracting the form collection from the http request and applying validation attributes. I would suggest constructing a validation attribute that implements the validation that you require. At the moment the validation that is being performed is almost meaningless as it is not telling you which field is invalid.
There is also the speed implication of performing this reflection many times on many requests, it could be ssssslllllllooooowwwwwww!!!
精彩评论