Build list of data validation attributes for a given element

橙三吉。 提交于 2021-02-07 09:12:47

问题


When using any of the Input Extension Helper Methods, like @Html.TextboxFor, any Validation Attributes from your model are automatically generated by the Razor engine (via ClientValidationEnabled/UnobtrusiveJavaScriptEnabled).

For example, take the following case which works fine

Model:

[Required]
public string QuestionOne { get; set; }

View:

@Html.TextBoxFor(model => model.QuestionOne) 
@Html.ValidationMessageFor(model => model.QuestionOne)

Generated Markup:

<input type="text" id="QuestionOne" name="QuestionOne" value=""
       data-val="true" data-val-required="The QuestionOne field is required." > 
<span class="field-validation-valid" data-valmsg-for="QuestionOne" data-valmsg-replace="true"></span>

In this case the attributes data-val="true" & data-val-required="The QuestionOne field is required." are picked up by Unobtrusive validation and the form element is successfully validated.


However, for extensibility reasons, I want to be able to generate the <input> element myself instead of using TextBoxFor. So my view would now look like this:

<input type="textbox" 
       id="@Html.IdFor(m => m.QuestionTwo)"
       name="@Html.NameFor(m => m.QuestionTwo)" 
       value="@Model.QuestionTwo"
       data-val="true" data-val-required="Selection is Required" />

@Html.ValidationMessageFor(model => model.QuestionTwo)

In this case, I'm faking the validation attribute output by just re-writing data-val="true" (etc) by hand, but this would have to be expanded to cover every single case.

Here's a running Demo in .NET Fiddle

Q: Can I build /return a list of data-val-* attributes for a given element?


回答1:


You can use the GetUnobtrusiveValidationAttributes() method of HtmlHelper to get the validation attributes associated with a specific property.

For example in the view

@{ var attributes = Html.GetUnobtrusiveValidationAttributes("QuestionTwo"); }

<input 
    type="textbox"
    @foreach(var attr in attributes)
    {
        @:@attr.Key="@attr.Value"
    }
    id="@Html.IdFor(m => m.QuestionTwo)"
    ....
/>

Note the @:@attr.Key="@attr.Value" line will give a warning (Missing attribute name) but will run correctly

Alternatively, you could use javaScript/jQuery to add the attributes

<script type="text/javascript">
    var attributes = @Html.Raw(Json.Encode(attributes));
    var input = $('#QuestionTwo');
    for(var i in attributes) {
        input.attr(i, attributes[i]);
    }
</script>

I have forked the DotNetFiddle here to show the working code for both options.

While the above code shows how it can be done, you should not be doing that. The HtmlHelper methods execute a lot of code your ignoring to ensure correct 2-way model binding, for example, the value attribute is determined by first checking for a value in ModelState, then in the ViewDataDictionary, and only if the previous values do not exist, does it use the value of the property (the second part of TextBoxFor displaying initial value, not the value updated from code explains the behavior).

Except for the incorrect value attribute, the code you have shown for the <input> is the same as will be generated by simply using @Html.TextBoxFor(m => m.Question2). I assume your real case is different, but if you cannot make use of TextBoxFor() and using an overload that accepts htmlAttributes to generate the html you need, then the correct approach is to create your own HtmlHelper method (and making use of existing methods in the HtmlHelper class and System.Web.Mvc.Html namespace)



来源:https://stackoverflow.com/questions/42999080/build-list-of-data-validation-attributes-for-a-given-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!