在MVC3中的HTML.ValidationMessageFor内部呈现HTML标记

时间:2012-01-19 21:49:30

标签: asp.net-mvc-3

我正在尝试将字段显示为字段验证消息的一部分。 我正在使用带有自定义错误消息的数据属性来设置它:

[Required(ErrorMessage = "Message <a href='#'>link</a>")]
public string Field{ get; set; }

但是当它渲染时,标签会被转义并逐字打印:

Message <a href='#'>link</a>

是否可以将链接作为验证消息的一部分进行正确渲染?

如果有人感兴趣,这就是我如何完成它

public static MvcHtmlString ValidationHTMLMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    return ValidationHTMLMessageFor(helper, expression, (object)null);
}
public static MvcHtmlString ValidationHTMLMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
    return ValidationHTMLMessageFor(helper, expression, new RouteValueDictionary(htmlAttributes));
}
public static MvcHtmlString ValidationHTMLMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
{
    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;
    }

    string errors = "";
    foreach (ModelError error in helper.ViewData.ModelState[name].Errors)
    {
        TagBuilder tag = new TagBuilder("span");
        tag.Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName);
        tag.MergeAttributes(htmlAttributes);
        tag.Attributes.Add("data-valmsg-for", name);
        tag.Attributes.Add("data-valmsg-replace", "true");

        var text = tag.ToString(TagRenderMode.StartTag);
        text += error.ErrorMessage;
        text += tag.ToString(TagRenderMode.EndTag);
        errors += text;
    }

    return MvcHtmlString.Create(errors);

}

感谢达林指出我正确的方向。我还发现这是我用作模板Customize Html.ValidationMessageFor doesn't work in client side

我是新手,所以如果有人有任何建议,请发帖。 谢谢!

5 个答案:

答案 0 :(得分:3)

上面的代码不适用于客户端验证,因为它不会生成客户端验证所需的标记。

这是对它的改进:

public static MvcHtmlString ValidationHTMLMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
{
  string propertyName = ExpressionHelper.GetExpressionText(expression);
  string name = helper.AttributeEncode(helper.ViewData.TemplateInfo.GetFullHtmlFieldName(propertyName));

  TagBuilder tag = new TagBuilder("span");
  tag.Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName);
  tag.MergeAttributes(htmlAttributes);
  tag.Attributes.Add("data-valmsg-for", name);
  tag.Attributes.Add("data-valmsg-replace", "true");
  var returnTag = new StringBuilder(tag.ToString(TagRenderMode.StartTag));

  if (helper.ViewData.ModelState[name] != null &&
      helper.ViewData.ModelState[name].Errors != null &&
      helper.ViewData.ModelState[name].Errors.Count > 0)
  {
    foreach (ModelError error in helper.ViewData.ModelState[name].Errors)
    {
      returnTag.Append(error.ErrorMessage);
    }
  }
  returnTag.Append(tag.ToString(TagRenderMode.EndTag));
  return MvcHtmlString.Create(returnTag.ToString());
}

感谢原帖 - 非常有帮助!

答案 1 :(得分:2)

是的,有可能但不能使用标准助手(ValidationSummaryValidationMessageFor)。如果要实现这一目的,则必须编写自定义帮助程序来呈现这些消息。您可以查看following post以获取如何编写自定义ValidationSummary帮助程序的示例,该帮助程序不会将错误消息HTML编码为标准错误消息。

答案 2 :(得分:1)

我正在使用MVC4所以我不能肯定地说MVC3。

我能够插入<br>标签(在我的情况下)的唯一方法是从Jerode的方法开始,但我还必须在消息字符串中放置一个标记并将其替换为剃刀。所以发送的消息是"Line 1[BR]Line2"。剃刀是@Html.Raw(Html.ValidationMessageFor(x => Model.MyProperty).ToString().Replace("[BR]", "&lt;br&gt;"))

希望有所帮助。

答案 3 :(得分:0)

另一种方法是将验证项放在Html.Raw中。

@Html.Raw(Html.ValidationMessageFor(x => Model.MyProperty))

这不像建议的那样好,但应该完成你想要的。

答案 4 :(得分:0)

基于@shycohen的回答:

    public static MvcHtmlString HtmlValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
    {
        string propertyName = ExpressionHelper.GetExpressionText(expression);
        string name = helper.AttributeEncode(helper.ViewData.TemplateInfo.GetFullHtmlFieldName(propertyName));

        TagBuilder tag = new TagBuilder("span");

        tag.Attributes.Add("data-valmsg-for", name);
        tag.Attributes.Add("data-valmsg-replace", "true");

        if (htmlAttributes != null)
        {
            tag.MergeAttributes((IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        tag.AddCssClass(HtmlHelper.ValidationMessageCssClassName);

        var returnTag = new StringBuilder(tag.ToString(TagRenderMode.StartTag));

        if (helper.ViewData.ModelState[name] != null &&
            helper.ViewData.ModelState[name].Errors != null &&
            helper.ViewData.ModelState[name].Errors.Count > 0)
        {
            foreach (ModelError error in helper.ViewData.ModelState[name].Errors)
            {
                returnTag.Append(error.ErrorMessage);
            }
        }

        returnTag.Append(tag.ToString(TagRenderMode.EndTag));

        return MvcHtmlString.Create(returnTag.ToString());
    }

htmlAttributes参数现在是可选的,并作为匿名对象传递给更接近的匹配ValidationMessageFor

另一个问题是无法通过htmlAttributes添加额外的课程,因为TagBuilder.MergeAttributes没有合并属性值。这是通过在合并属性后使用TagBuilder.AddCssClass 来设置验证类来解决的。