可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a Model with 4 properties which are of type string. I know you can validate the length of a single property by using the StringLength annotation. However I want to validate the length of the 4 properties combined.
What is the MVC way to do this with data annotation?
I\'m asking this because I\'m new to MVC and want to do it the correct way before making my own solution.
回答1:
You could write a custom validation attribute:
public class CombinedMinLengthAttribute: ValidationAttribute
{
public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
{
this.PropertyNames = propertyNames;
this.MinLength = minLength;
}
public string[] PropertyNames { get; private set; }
public int MinLength { get; private set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
if (totalLength < this.MinLength)
{
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
}
and then you might have a view model and decorate one of its properties with it:
public class MyViewModel
{
[CombinedMinLength(20, \"Bar\", \"Baz\", ErrorMessage = \"The combined minimum length of the Foo, Bar and Baz properties should be longer than 20\")]
public string Foo { get; set; }
public string Bar { get; set; }
public string Baz { get; set; }
}
回答2:
Self validated model
Your model should implement an interface IValidatableObject
. Put your validation code in Validate
method:
public class MyModel : IValidatableObject
{
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Title == null)
yield return new ValidationResult(\"*\", new [] { nameof(Title) });
if (Description == null)
yield return new ValidationResult(\"*\", new [] { nameof(Description) });
}
}
Please notice: this is a server-side validation. It doesn\'t work on client-side. You validation will be performed only after form submission.
回答3:
ExpressiveAnnotations gives you such a possibility:
[Required]
[AssertThat(\"Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50\")]
public string FieldA { get; set; }
回答4:
Background:
Model validations are required for ensuring that the received data we receive is valid and correct so that we can do the further processing with this data. We can validate a model in an action method. The built-in validation attributes are Compare, Range, RegularExpression, Required, StringLength. However we may have scenarios wherein we required validation attributes other than the built-in ones.
Custom Validation Attributes
public class EmployeeModel
{
[Required]
[UniqueEmailAddress]
public string EmailAddress {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public int OrganizationId {get;set;}
}
To create a custom validation attribute, you will have to derive this class from ValidationAttribute.
public class UniqueEmailAddress : ValidationAttribute
{
private IEmployeeRepository _employeeRepository;
[Inject]
public IEmployeeRepository EmployeeRepository
{
get { return _employeeRepository; }
set
{
_employeeRepository = value;
}
}
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
var model = (EmployeeModel)validationContext.ObjectInstance;
if(model.Field1 == null){
return new ValidationResult(\"Field1 is null\");
}
if(model.Field2 == null){
return new ValidationResult(\"Field2 is null\");
}
if(model.Field3 == null){
return new ValidationResult(\"Field3 is null\");
}
return ValidationResult.Success;
}
}
Hope this helps. Cheers !
References
- Code Project - Custom Validation Attribute in ASP.NET MVC3
- Haacked - ASP.NET MVC 2 Custom Validation
回答5:
To improve Darin\'s answer, it can be bit shorter:
public class UniqueFileName : ValidationAttribute
{
private readonly NewsService _newsService = new NewsService();
public override bool IsValid(object value)
{
if (value == null) { return false; }
var file = (HttpPostedFile) value;
return _newsService.IsFileNameUnique(file.FileName);
}
}
Model:
[UniqueFileName(ErrorMessage = \"This file name is not unique.\")]
Do note that an error message is required, otherwise the error will be empty.
回答6:
A bit late to answer, but for who is searching.
You can easily do this by using an extra property with the data annotation:
public string foo { get; set; }
public string bar { get; set; }
[MinLength(20, ErrorMessage = \"too short\")]
public string foobar
{
get
{
return foo + bar;
}
}
That\'s all that is too it really. If you really want to display in a specific place the validation error as well, you can add this in your view:
@Html.ValidationMessage(\"foobar\", \"your combined text is too short\")
doing this in the view can come in handy if you want to do localization.
Hope this helps!