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

Asp.net mvc 如何在ASP MVC中自定义Html.ValidationMessageFor,asp.net-mvc,asp.net-mvc-3,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> 此字段为必填字段 是的,只需为字段

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

我想做一些类似的事情:

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

此字段为必填字段


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

[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字段中更改消息:)
希望得到以下帮助:)

我不确定是否可以使用
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));
    }
}

您可以实现自己的validationmessageforhelper来发出所需的输出,或者使用一些javascript来添加/修改呈现的HTML代码,但是定制的validationmessageforimplementation是更干净的方法IMHO

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

实施提示

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

FormContext formContext = htmlHelper.ViewContext.ClientValidationEnabled ? htmlHelper.ViewContext.FormContext : null;
其他一些方法在ValidationExtension中是私有的,比如GetUserErrorMessageOrDefault,您也需要复制这些代码。避免代码重复的方法是让ValidationExtensions.ValidationMessageFor呈现封装在范围中的验证消息字符串,然后根据需要更改呈现的字符串。请记住,如果没有发现错误,则返回“null”,如果启用了不引人注目的JavaScript,则需要data-HTML属性


您可以从

下载ASP.NET MVC 3源代码。在我的例子中,唯一需要更改默认标记生成的是,它跨越了行为结果,并设置了空白

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

也许这对某些人有帮助。

我用了另一种方法:

    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"));
    }
public static MvcHtmlString DivValidationMessageFor(此HtmlHelper HtmlHelper,表达式)
{
返回MvcHtmlString.Create(htmlhelp.ValidationMessageFor(expression.ToString().Replace(“span”、“div”));
}
这样,您可以使用内置方式,但可以使用div替换跨度


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

也许您可以将该代码

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

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

public static MvcHtmlString ValidationMessageAsStringFor(此HtmlHelper,表达式)
{
var field=ExpressionHelper.GetExpressionText(表达式);
字符串modelName=helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(字段);
如果(!helper.ViewData.ModelState.ContainsKey(modelName))
{
返回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)
{
返回null;
}
var errorMessage=GetUserErrorMessageOrDefault(helper.ViewContext.HttpContext,modelError,modelState);
返回MvcHtmlString.Create(errorMessage);
}
私有静态字符串GetUserErrorMessageOrDefault(HttpContextBase httpContext,ModelError错误,ModelState ModelState)
{
如果(!string.IsNullOrEmpty(error.ErrorMessage))
{
返回error.error消息;
}
if(modelState==null)
{
返回null;
}
返回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>

@Html.ValidationMessageAsStringFor(m=>m.FieldName)


这正是我想要的。我还不了解验证插件的问题,但我会调查一下。谢谢这对我来说很好,但是请确保在System.Web.Mvc.Html名称空间中声明静态帮助器类,它将非常好地工作。您如何实际更改“ValidationMessageFor”消息生成的Html。我不是说把它放在另一个分区里。有可能吗?@gyozokudor请看下面我的答案。我创建它是因为我看到了这个答案:
'HtmlHelper'不包含“ValidationMessageFor”的定义。
我喜欢这种方法。比为这么小的更改复制所有ValidationMessageHelper代码容易得多。
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;
}
<div class="field-error-box">
    <div class="top"></div>
    <div class="mid"><p>@Html.ValidationMessageAsStringFor(m => m.FieldName)</p></div>
</div>