Ich hatte das gleiche Problem und konnte es lösen, indem ich die IValidatableObject-Schnittstelle in meinem Ansichtsmodell implementierte.
public class RegisterViewModel : IValidatableObject
{
public static string PasswordLengthErrorMessage => $"The password must be at least {PasswordMinimumLength} characters";
public const int PasswordMinimumLength = 8;
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var errorList = new List<ValidationResult>();
if ((Password?.Length ?? 0 ) < PasswordMinimumLength)
{
errorList.Add(new ValidationResult(PasswordLengthErrorMessage, new List<string>() {"Password"}));
}
return errorList;
}
}
Das Markup im Rasiermesser ist dann ...
<div class="form-group">
@Html.LabelFor(m => m.Password)
@Html.PasswordFor(m => m.Password, new { @class = "form-control input-lg" }
<div class="password-helper">Must contain: 8 characters, 1 upper-case, 1 lower-case
</div>
@Html.ValidationMessagesFor(m => m.Password, new { @class = "text-danger" })
</div>
Das funktioniert wirklich gut. Wenn ich stattdessen versuche, [StringLength] zu verwenden, ist der gerenderte HTML-Code einfach nicht korrekt. Die Validierung sollte wie folgt erfolgen:
<span class="text-danger field-validation-invalid field-validation-error" data-valmsg-for="Password" data-valmsg-replace="true"><span id="Password-error" class="">The Password should be a minimum of 8 characters long.</span></span>
Mit dem StringLengthAttribute wird der gerenderte HTML-Code als ValidationSummary angezeigt, was nicht korrekt ist. Das Lustige ist, dass wenn der Validator ausfällt, die Übermittlung immer noch blockiert ist!