THX-1138
THX-1138

Reputation: 21730

Using ASP.NET MVC ValidateFor HTML helper together with unobtrusive validation

  1. Is it possible to use Html.ValidateFor together with unobtrusive validation? I want to be able to do following:

    < !-- I want to specify validation using data-val* attributes -->
    < input type="text" data-val-required/>

    < !-- I want to use HTML helper to inject data-val* attributes using view model attributes -->
    @Html.TextBoxFor(m => m.Title)

    < !-- I want also be able to render input control myself, but also include validation from viewmodel attributes, and eat it too -->
    @{ Html.ValidateFor(m => m.Age); }

  2. Why ValidateFor disabled when unobtrusive validation is enabled? What is an easy way to use both?

Upvotes: 0

Views: 4486

Answers (1)

THX-1138
THX-1138

Reputation: 21730

I added an HTML extension method that will inspect model metadata and yield all data-val* attributes (for consumption by jquery.unobtrusive.validation).

This way I have full control over how control is rendered (sometimes Html.*For family of methods would produce name and id attributes that don't suit my needs, also adding extra arguments might get clunky).

Note, you still need to have input control inside form element (required by jquery.unobtrusive.validation).

public static MvcHtmlString Validation<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) {
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    IDictionary<string, object> dataValAttrs = html.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);

    StringBuilder stringBuilder = new StringBuilder();
    foreach (var dataValAttr in dataValAttrs) {
        stringBuilder.Append(' ').Append(dataValAttr.Key).Append("=\"").Append(dataValAttr.Value).Append('"');
    }
    return new MvcHtmlString(stringBuilder.ToString());
}

And here is how this method is to be used:

<textarea name="Description" class="input-block-level" @Html.Validation(m => m.FormData.Description)></textarea>
@Html.ValidationMessage("Description")

Notice that you can't use Html.ValidationMessageFor version here, since it will create name FormData_Description which is different from Description I want in this case (for the purpose of POST action binding to a FormData object.

Upvotes: 2

Related Questions