简体   繁体   中英

Client-side validation difference between Html.TextBoxFor/Html.TextAreaFor and Html.EditorFor (with [DataType(DataType.MultilineText)])

I am using client-side validation (unobtrusive) in ASP.NET MVC 3/Razor and I got it to work on a <textarea> by using Html.EditorFor and specifying DataType.MultilineText, but should not Html.TextAreaFor also have client-side validation?

[Required(ErrorMessage = "Foo")]
public string Message { get; set; }

// Does add client-side validation
@Html.TextBoxFor(m => m.Message)

// Does NOT add client-side validation
@Html.TextAreaFor(m => m.Message)

[Required(ErrorMessage = "Foo")]
[DataType(DataType.MultilineText)]
public string Message { get; set; }

// Does add client-side validation (and multiline)
@Html.EditorFor(m => m.Message)

// Does NOT add client-side validation
@Html.TextAreaFor(m => m.Message)

<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

Your example above works fine for me. I wonder - was this a precise example, or was it simplified from a real world problem? I have found this exact behavior when using a model with nested properties.

So, for example, if I change your model to look like this:

public class MyModelObject
{
    [Required(ErrorMessage = "Foo")]
    [DataType(DataType.MultilineText)]
    public string Message { get; set; }
}

public class MyModel
{
    public MyModelObject MyObject { get; set; }
}

Then I reproduce the exact problem you mentioned.

@Html.EditorFor(x => x.MyObject.Message)

generates the jquery validation attributes as expected:

<textarea class="text-box multi-line input-validation-error" data-val="true" data-val-required="Foo" id="MyObject_Message" name="MyObject.Message"></textarea>

But, this:

@Html.TextAreaFor(x => x.MyObject.Message)

Does not:

<textarea cols="20" id="MyObject_Message" name="MyObject.Message" rows="2"></textarea>

If this does in fact describe your issue, it looks like this has been reported as a bug: http://aspnet.codeplex.com/workitem/8576

As obliojoe suggested in his answer, this bug appears when the expression is more complex than a simple property reference.

I have implemented replacement helpers that work around this problem. The trick is to obtain correct model metadata, pass it to HtmlHelper.GetUnobtrusiveValidationAttributes() and then pass the received attributes to the original TextAreaFor() helper:

public static MvcHtmlString TextAreaWithValidationFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    var modelMetadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    var name = ExpressionHelper.GetExpressionText(expression);
    IDictionary<string, object> validationAttributes = helper.GetUnobtrusiveValidationAttributes(name, modelMetadata);
    return TextAreaExtensions.TextAreaFor(helper, expression, validationAttributes);
}

I attached a more developed version (which provides all TextAreaFor overloads, including those with htmlAttributes ) of this code to the bug reported on CodePlex .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM