Reputation: 3026
I have a requirement to add StringLengthAttribute
validation to a lot of models in the existing ASP.NET MVC 4 project and am trying to do this automatically through my own model metadata provider derived from DataAnnotationsModelMetadataProvider
.
It works perfectly with RequiredAttribute
and some other data annotation attributes (I get both client-side and server-side validation working), however validation for the string length is not added - find the minimal example below.
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
StringLengthAttribute lengthAttribute = new StringLengthAttribute(256);
attributes = attributes.Union(new[] { lengthAttribute });
return base.CreateMetadata(attributes,
containerType,
modelAccessor,
modelType,
propertyName);
}
}
So, looks like StringLengthAttribute
it being handled in some special way. Any ideas on how to make it work or a better implementation idea?
Upvotes: 1
Views: 1923
Reputation: 2605
After playing around, I couldn't get the StringLength attribute to fire either.
Not ideal, but i guess an alternative solution is to the use a global ModelValidatorProvider class. Granted you won't get the built in Javascript that is provided by the StringLengthAttribute and you'd be writing your own logic, but its a possible quick fix for a problem you can solve later?
public class MyCustomModelValidatorProvider : ModelValidatorProvider
{
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
return new List<ModelValidator>() { new MyCustomModelValidator(metadata, context) };
}
public class MyCustomModelValidator : ModelValidator
{
public MyCustomModelValidator(ModelMetadata metadata, ControllerContext context)
: base(metadata, context)
{ }
public override IEnumerable<ModelValidationResult> Validate(object container)
{
var model = this.Metadata.Model;
if (model is string)
{
var value = model as string;
if (String.IsNullOrEmpty(value) || value.Length > 256)
{
var validationResult = new ModelValidationResult();
validationResult.Message = (this.Metadata.DisplayName ?? this.Metadata.PropertyName)
+ " needs to be no more then 256 characters";
return new List<ModelValidationResult>() { validationResult };
}
}
return new List<ModelValidationResult>();
}
}
}
Add MyCustomModelValidator to the collection in Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// Use LocalDB for Entity Framework by default
Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ModelValidatorProviders.Providers.Add(new MyCustomModelValidatorProvider());
}
Upvotes: 1