【问题标题】:How to customize Html.ValidationMessageFor in ASP MVC如何在 ASP MVC 中自定义 Html.ValidationMessageFor
【发布时间】:2011-12-05 04:22:15
【问题描述】:

是否可以自定义 Html.ValidationMessageFor 方法以生成不同的 HTML?

我想做类似的事情:

<div class="field-error-box">
    <div class="top"></div>
    <div class="mid"><p>This field is required.</p></div>
</div>

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3


    【解决方案1】:

    我不确定是否可以使用paragraph 代替默认的span,因为验证插件可能无法放置错误消息。但是对于 div -s,这很容易——你可以编写自定义的 html 助手。

    这些方面的东西(可能需要进一步测试/编码)。您需要在视图中包含此静态扩展方法的命名空间,或直接将其放入System.Web.Mvc.Html

    public static class Validator
    {
        public static MvcHtmlString MyValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        {
            TagBuilder containerDivBuilder = new TagBuilder("div");
            containerDivBuilder.AddCssClass("field-error-box");
    
            TagBuilder topDivBuilder = new TagBuilder("div");
            topDivBuilder.AddCssClass("top");
    
            TagBuilder midDivBuilder = new TagBuilder("div");
            midDivBuilder.AddCssClass("mid");
            midDivBuilder.InnerHtml = helper.ValidationMessageFor(expression).ToString();
    
            containerDivBuilder.InnerHtml += topDivBuilder.ToString(TagRenderMode.Normal);
            containerDivBuilder.InnerHtml += midDivBuilder.ToString(TagRenderMode.Normal);
    
            return MvcHtmlString.Create(containerDivBuilder.ToString(TagRenderMode.Normal));
        }
    }
    

    如您所见,这使用默认的ValidationMessageFor 方法,不会干扰验证插件错误消息处理。

    你可以简单地使用它,作为默认的验证消息助手

    @Html.MyValidationMessageFor(model => model.SomeRequiredField)
    

    【讨论】:

    • 这正是我想要的。我还不明白验证插件的问题,但我会调查一下。谢谢!
    • 这对我来说效果很好,但请确保在 System.Web.Mvc.Html 命名空间中声明您的静态帮助程序类,它会非常有效。
    • 您如何实际更改由“ValidationMessageFor”消息生成的 html。我不是在谈论将它包装在另一个 div 中。有可能吗?
    • @gyozokudor 请参阅下面的答案。我创建它是因为我看到了这个答案:'HtmlHelper&lt;TModel&gt;' does not contain a definition for 'ValidationMessageFor'
    【解决方案2】:

    我用了另一种方式:

        public static MvcHtmlString DivValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return MvcHtmlString.Create(htmlHelper.ValidationMessageFor(expression).ToString().Replace("span", "div"));
        }
    

    这样你可以使用内置的方式,但是用一个div替换span。

    如果您需要函数的任何其他重载,只需根据需要复制即可。

    【讨论】:

    • 我喜欢这种方法。比复制所有 ValidationMessageHelper 代码进行如此小的更改要容易得多。
    【解决方案3】:

    您可以实现自己的 ValidationMessageFor 助手来发出所需的输出或使用一些 javascript 来添加/修改呈现的 HTML 代码,但自定义 ValidationMessageFor 实现是更简洁的方法恕我直言。

    要实现您自己的 ValidationMessageFor 帮助器,请查看 ASP.NET MVC 源代码中的 ValidationExtensions.ValidationMessageFor 和 ValidationMessageHelper 方法。

    实现提示

    由于 GetFormContextForClientValidation 是内部的,因此您必须通过在代码中复制内部功能来解决该实现:

    FormContext formContext = htmlHelper.ViewContext.ClientValidationEnabled ? htmlHelper.ViewContext.FormContext : null;
    

    其他一些方法在 ValidationExtensions 中是私有的,例如 GetUserErrorMessageOrDefault,您也需要复制该代码。为了避免重复代码,您可以做的是让 ValidationExtentensions.ValidationMessageFor 呈现包装在跨度中的验证消息字符串,然后根据您的要求更改呈现的字符串。请记住,如果没有发现错误,则返回“null”,并且您需要 data-HTML 属性以防您启用了不显眼的 JavaScript。

    您可以从here 下载 ASP.NET MVC 3 源代码

    【讨论】:

      【解决方案4】:

      在我的情况下,唯一需要更改默认标签生成的情况是,跨越行为会导致恼人的边距设置。

      我通过使用 'display: block' 解决了这个问题

      也许这对某些人有帮助..

      【讨论】:

        【解决方案5】:

        也许你可以把那个代码

        string propertyName = ExpressionHelper.GetExpressionText(expression);
        string name = helper.AttributeEncode(helper.ViewData.TemplateInfo.GetFullHtmlFieldName(propertyName));
        
        if (helper.ViewData.ModelState[name] == null ||
            helper.ViewData.ModelState[name].Errors == null ||
            helper.ViewData.ModelState[name].Errors.Count == 0)
            {
                return MvcHtmlString.Empty;
            }
        

        在应答函数的顶部,这样 div 就不会出现在表单加载中。

        【讨论】:

          【解决方案6】:

          我创建了ValidationMessageAsStringFor,它只是将错误消息作为字符串返回。基本上就是ValidationMessageFor的简化版:

          public static MvcHtmlString ValidationMessageAsStringFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
          {
              var field = ExpressionHelper.GetExpressionText(expression);
              string modelName = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(field);
          
              if (!helper.ViewData.ModelState.ContainsKey(modelName))
              {
                  return null;
              }
          
              var modelState = helper.ViewData.ModelState[modelName];
              var modelErrors = (modelState == null) ? null : modelState.Errors;
              var modelError = ((modelErrors == null) || (modelErrors.Count == 0)) ? null : modelErrors.FirstOrDefault(m => !String.IsNullOrEmpty(m.ErrorMessage)) ?? modelErrors[0];
          
              if (modelError == null)
              {
                  return null;
              }
          
              var errorMessage = GetUserErrorMessageOrDefault(helper.ViewContext.HttpContext, modelError, modelState);
          
              return MvcHtmlString.Create(errorMessage);
          }
          
          private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState)
          {
              if (!string.IsNullOrEmpty(error.ErrorMessage))
              {
                  return error.ErrorMessage;
              }
          
              if (modelState == null)
              {
                  return null;
              }
          
              return modelState.Value?.AttemptedValue;
          }
          

          有了这个并在导入包含新助手的命名空间后,只需创建您需要的 HTML 代码:

          <div class="field-error-box">
              <div class="top"></div>
              <div class="mid"><p>@Html.ValidationMessageAsStringFor(m => m.FieldName)</p></div>
          </div>
          

          【讨论】:

            【解决方案7】:

            是的,只需为该字段使用元模型:

            [MetadataType(typeof(YourMetaData))]
            public partial class YOURCLASS
            {
                [Bind(Exclude = "objID")]
                public class YourMetaData
                {
                    [Required(AllowEmptyStrings = false, ErrorMessage = "Please enter a name")]
                    public object Name { get; set; }
                }
            }
            

            在 ErrorMessage 字段中更改您的消息 :) 希望对您有所帮助:)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-23
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多