为 ASP.NET MVC 2.0 中的视图中的 [Required] 字段定义标记

发布于 2024-09-04 05:23:56 字数 240 浏览 9 评论 0原文

我们有一个模型,其属性用 [Required] 装饰,非常适合验证。但是,我们想要做的是在视图中用星号(或其他样式)标记这些必填字段,以表示在用户输入任何数据进行验证之前它们是必需的。

我似乎无法找到 MVC 框架中内置的任何内容来允许我执行此操作,因此想知道是否有其他人已经解决了这个问题以及如何解决?

最终,我们试图防止的是,如果我们随后从模型属性中删除 [Required],则需要在两个位置更改代码。

非常感谢

We have a model with properties decorated with [Required] which works great for validation. However, what we'd like to do is mark those required fields in the view with an asterisk (or some other style) to denote they are required before the user enters any data for validation.

I don't seem to be able to find anything built into the MVC framework to allow me to do this and therefore wondered if anyone else had already solved this and how?

Ultimately what we're trying to prevent is the need to change code in two places if we subsequently remove a [Required] from a model property.

Many Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清音悠歌 2024-09-11 05:23:56

您可以为此构建自己的 HtmlHelper 扩展:

public static string RequiredMarkFor<TModel, TValue>(this HtmlHelper html, Expression<Func<TModel, TValue>> expression)
{
    if(ModelMetadata.FromLambdaExpression(expression, html.ViewData).IsRequired)
         return "*";
    else
         return string.Empty;
}

You can build your own HtmlHelper extension for this:

public static string RequiredMarkFor<TModel, TValue>(this HtmlHelper html, Expression<Func<TModel, TValue>> expression)
{
    if(ModelMetadata.FromLambdaExpression(expression, html.ViewData).IsRequired)
         return "*";
    else
         return string.Empty;
}
花开半夏魅人心 2024-09-11 05:23:56

Gregoire 和 Faxanadu 的解决方案的问题是,当使用正常验证对字段进行验证并且使用“Html.ValidationMessageFor()”时,始终显示“*”。

因此,如果您使用这样的 html 扩展:

@Html.EditorFor(model => model.Email)
@Html.RequiredFieldFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)

您将看到重复的 *,以防字段出现验证错误。

我基于 this 它还会检查该字段是否已验证。

private static Type[] RequiredTypes = new Type[] { typeof(CustomRequiredAttribute), typeof(RequiredAttribute) };

/// <summary>
/// Generate a <span class="field-validation-error">*<< element.
/// 
/// See http://koenluyten.blogspot.com/2011/06/denote-required-fields-in-aspnet-mvc-3.html
/// </summary>
public static MvcHtmlString RequiredFieldFor<TModel, TValue>(this HtmlHelper<TModel> html,
    Expression<Func<TModel, TValue>> expression, string validationMessage = "*")
{
    // Get the metadata for the model
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    string fieldName = metadata.PropertyName;

    // Check if the field is required
    bool isRequired = metadata
        .ContainerType.GetProperty(fieldName)
        .GetCustomAttributes(false)
        .Count(m => RequiredTypes.Contains(m.GetType())) > 0;

    // Check if the field is validated
    bool isValidated = html.ViewData.ModelState[fieldName] != null;

    // If the field is required and not validated; generate span with an asterix
    if (isRequired && !isValidated)
    {
        var span = new TagBuilder("span");
        span.AddCssClass("field-validation-error");
        span.SetInnerText(validationMessage);

        return MvcHtmlString.Create(span.ToString(TagRenderMode.Normal));
    }

    return null;
}

The problem with the solution from Gregoire and Faxanadu is that the "*" is always displayed, also when the field is validated using the normal validation and you use 'Html.ValidationMessageFor()'.

So if you use the html extension like this:

@Html.EditorFor(model => model.Email)
@Html.RequiredFieldFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)

You'll see duplicate * in case the field has validation errors.

I've made this modified extension, based on this which does also check if the field was validated.

private static Type[] RequiredTypes = new Type[] { typeof(CustomRequiredAttribute), typeof(RequiredAttribute) };

/// <summary>
/// Generate a <span class="field-validation-error">*<< element.
/// 
/// See http://koenluyten.blogspot.com/2011/06/denote-required-fields-in-aspnet-mvc-3.html
/// </summary>
public static MvcHtmlString RequiredFieldFor<TModel, TValue>(this HtmlHelper<TModel> html,
    Expression<Func<TModel, TValue>> expression, string validationMessage = "*")
{
    // Get the metadata for the model
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    string fieldName = metadata.PropertyName;

    // Check if the field is required
    bool isRequired = metadata
        .ContainerType.GetProperty(fieldName)
        .GetCustomAttributes(false)
        .Count(m => RequiredTypes.Contains(m.GetType())) > 0;

    // Check if the field is validated
    bool isValidated = html.ViewData.ModelState[fieldName] != null;

    // If the field is required and not validated; generate span with an asterix
    if (isRequired && !isValidated)
    {
        var span = new TagBuilder("span");
        span.AddCssClass("field-validation-error");
        span.SetInnerText(validationMessage);

        return MvcHtmlString.Create(span.ToString(TagRenderMode.Normal));
    }

    return null;
}
暖阳 2024-09-11 05:23:56

如果您在使用“ModelMetadata.FromLambdaExpression”时收到“无效参数”错误,请确保为 HtmlHelper 指定通用类型参数。这是格雷瓜尔解决方案的修订版本:

public static string RequiredMarkFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        if (ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).IsRequired)
            return "*";
        else
            return string.Empty;
    }

If you are getting an "invalid arguments" error when using "ModelMetadata.FromLambdaExpression", make sure you specify a generic type parameter for HtmlHelper. Here is a revised version of Gregoire's solution:

public static string RequiredMarkFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        if (ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).IsRequired)
            return "*";
        else
            return string.Empty;
    }
写下不归期 2024-09-11 05:23:56

如果您使用完整表单模板化帮助程序 EditorFor 和 DisplayFor,您需要自定义您自己的 Object.ascx 版本。

Brad Wilson 有一篇很棒的博客文章,概述了这一点:

http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

会发生什么如果 ModelMetadata 上的 IsRequired 属性将为 true。 Object.ascx 内部:

<%=propertu.IsRequired ? "*" : ""%>

如果您不使用模板化帮助程序,则必须编写自己的 html 帮助程序。您的观点如何?

If you are using full form templated helpers EditorFor and DisplayFor you need to customize your own version of Object.ascx.

Brad Wilson has an awesome blog post which outlines this:

http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

What happens it the IsRequired property on ModelMetadata will be true. Inside Object.ascx:

<%=propertu.IsRequired ? "*" : ""%>

If your not using templated helpers you'd have to write your own html helper. What do your views look like?

春庭雪 2024-09-11 05:23:56

我现在的问题有点老了,但我正在努力使用 jquery 找到一个不显眼的解决方案。

我的目标是获取所有标有 data-val-required 属性的输入,然后设置其标签元素标记为 for

以下是示例 jquery 代码:

$('[data-val-required]').each(function() { 
    var $label = $('label[for=' + this.name + ']');

    //from here we can manipulate the label element
    $label.css('font-weight', 'bold');
    $label.text($label.text() + ' *');
});

I now the question is a little old, but I am working to an unobstrusive solution using just jquery.

My goal is to get all inputs marked with data-val-required attribute, and then set its label elementes markeds with attribute for

Here is the sample jquery code:

$('[data-val-required]').each(function() { 
    var $label = $('label[for=' + this.name + ']');

    //from here we can manipulate the label element
    $label.css('font-weight', 'bold');
    $label.text($label.text() + ' *');
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文