The solution I have come to, is to create an extension for the HtmlHelper class that creates custom validated controls, where the validation attributes are added to the generated HTML.
public static MvcHtmlString ValidatedTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> attributes)
{
var message = GetMessage(htmlHelper, expression);
return htmlHelper.TextBoxFor(expression, new Dictionary<string, object>(attributes)
{
{ "data-val", "true" },
{ "data-val-required", message ?? "Must not be empty"},
});
}
private static string GetMessage<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
PropertyInfo[] props = metadata.ContainerType.GetProperties();
string message = null;
var info = props.First(prop => prop.Name == metadata.PropertyName);
var attribute = info.GetCustomAttribute(typeof (RequiredAttribute)) as RequiredAttribute;
if (attribute != null)
{
message = attribute.ErrorMessage;
if (string.IsNullOrEmpty(message))
{
var resource = attribute.ErrorMessageResourceType;
var resourceName = attribute.ErrorMessageResourceName;
if (resource == null || resourceName == null)
return null;
message = new ResourceManager(resource).GetString(resourceName);
}
}
return message;
}