如何在ASP MVC中自定义Html.ValidationMessageFor

时间:2011-12-05 04:22:15

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

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

我想做类似的事情:

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

7 个答案:

答案 0 :(得分:28)

我不确定是否可以使用p aragraph而不是默认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)

答案 1 :(得分:7)

我用另一种方式:

    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。

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

答案 2 :(得分: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呈现包含在span中的验证消息字符串,然后根据您的要求更改呈现的字符串。请记住,如果未发现错误,则返回“null”,并且如果您启用了不显眼的JavaScript,则需要data-HTML属性。

您可以从here

下载ASP.NET MVC 3源代码

答案 3 :(得分:2)

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

我使用'display:block'

解决了这个问题

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

答案 4 :(得分:0)

也许你可以把那段代码

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不会出现在表单加载中。

答案 5 :(得分:0)

我创建了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>

答案 6 :(得分:-2)

是的,只需在字段中使用元模型:

[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字段中更改您的消息:) 希望这有帮助:)