ASP.Net Core MVC - Client-side validation for custom attribute
The IClientModelValidator
is in fact the right interface. I've made a contrived sample implementation below.
Note:
There was a breaking change to the IClientModelValidator
interface between RC1 and RC2. Both options are presented below - the rest of the code is the same between both versions.
Attribute (RC2 and beyond)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class CannotBeRedAttribute : ValidationAttribute, IClientModelValidator
{
public override bool IsValid(object value)
{
var message = value as string;
return message?.ToUpper() == "RED";
}
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-cannotbered", errorMessage);
}
private bool MergeAttribute(
IDictionary<string, string> attributes,
string key,
string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}
Attribute (RC1)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class CannotBeRedAttribute : ValidationAttribute, IClientModelValidator
{
public override bool IsValid(object value)
{
var message = value as string;
return message?.ToUpper() == "RED";
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
ClientModelValidationContext context)
{
yield return new ModelClientValidationRule(
"cannotbered",
FormatErrorMessage(ErrorMessage));
}
}
Model
public class ContactModel
{
[CannotBeRed(ErrorMessage = "Red is not allowed!")]
public string Message { get; set; }
}
View
@model WebApplication22.Models.ContactModel
<form asp-action="Contact" method="post">
<label asp-for="Message"></label>
<input asp-for="Message" />
<span asp-validation-for="Message"></span>
<input type="submit" value="Save" />
</form>
@section scripts {
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
$.validator.addMethod("cannotbered",
function (value, element, parameters) {
return value.toUpperCase() !== "RED";
});
$.validator.unobtrusive.adapters.add("cannotbered", [], function (options) {
options.rules.cannotbered = {};
options.messages["cannotbered"] = options.message;
});
</script>
}
m.edmondson
Many of my best answers are written up fully and ported to my blog. This (along with my other abstract ideas) allows me to create an online portfolio of important and interesting information for both referencing and for others to learn from. View my LinkedIn Profile.
Updated on April 08, 2020Comments
-
m.edmondson about 4 years
In previous versions of the MVC framework custom validation would be achieved through implementing
IClientValidatable
and theGetClientValidationRules
method.However in ASP.Net Core MVC we do not have this interface, although we do have
IClientModelValidator
which a defining a very similar method. The implementation of which never gets called however.So - how do we implement client-side validation for a custom attribute in ASP.NET Core MVC?