如何扩展Html.ValidationMessage以便我可以将图像包含为错误?

时间:2022-06-05 04:02:47

I would like to reduce the following code. The below code works, however it is not very tidy etc.

我想减少以下代码。以下代码有效,但不是很整洁等。

    <label for="Name">Name:</label><%= Html.TextBox("Name")%><% 
    if (!string.IsNullOrEmpty(Html.ValidationMessage("Name"))) {
        string Error = HtmlRemoval.StripTags(Html.ValidationMessage("Name")); %>
        <img src="Error.gif" alt="Error" title="<%= Error %>" /><%
    }
    %>

I have read that I need to extend the Html helper so that I can return an image instead of the text containing the default element and textual error.

我已经读过我需要扩展Html帮助器,以便我可以返回一个图像而不是包含默认元素和文本错误的文本。

I can't seem to find any articles or general advice on how I would accomplish this. I am still very new to ASP.NET MVC. Any advice would be greatly appreciated.

我似乎无法找到关于如何实现这一目标的任何文章或一般性建议。我仍然是ASP.NET MVC的新手。任何建议将不胜感激。

7 个解决方案

#1


13  

You can extend HtmlHelper like:

您可以扩展HtmlHelper,如:

public static class CustomHtmlHelper {

  public static string ValidationImage(this HtmlHelper helper, string name) {
    if (helper.ViewData.ModelState[name] == null || helper.ViewData.ModelState[name].Errors == null) {
      return String.Empty;
    }
    TagBuilder tag = new TagBuilder("img");
    tag.Attributes.Add("src", "Error.gif");
    tag.Attributes.Add("alt", "Error");
    tag.Attributes.Add("title", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
    return tag.ToString(TagRenderMode.SelfClosing);
  }

}

Then in your page import the class containing the extension method

然后在您的页面中导入包含扩展方法的类

<%@ Import Namespace="CustomHtmlHelperNamespace" %>

Then add the following to your page:

然后将以下内容添加到您的页面:

<label for="Name">Name:</label>
<%= Html.TextBox("Name")%>
<% Html.ValidationImage("Name") %>

For more on extending HtmlHelper try here but basically this extends HtmlHelper, checks the ViewState for a an error on the value parsed in name ("Name" in your case) and if it contains an error generates the HTML needed to render the image. The title attribute for the image will contain the validation message for field "Name"

有关扩展HtmlHelper的更多信息,请尝试此处,但基本上这会扩展HtmlHelper,检查ViewState是否在名称中解析的值上出现错误(在您的情况下为“Name”),如果包含错误,则生成呈现图像所需的HTML。图像的title属性将包含字段“Name”的验证消息

#2


1  

You can extend the Html Helper to add a method by making a class like below. Not 100% this is what you're asking, but here goes:

您可以扩展Html Helper以通过创建如下所示的类来添加方法。不是100%这是你要问的,但是这里是:

public class HtmlHelperExtensions {

    public static string GetMeSomething(this HtmlHelper helper)
    {
        //... Do things here. ...
    }
}

Once you have something like that, you can call Html.GetMeSomething, and it will return a string or whatever you declare your return type as.

一旦你有这样的东西,你可以调用Html.GetMeSomething,它将返回一个字符串或任何你声明你的返回类型为。

#3


1  

Rolling you own ValidationMessage helper to render an image tag may be your best bet... The built-in helper will render a tag such as

滚动你自己的ValidationMessage帮助器来渲染图像标签可能是你最好的选择......内置帮助器将渲染一个标签,如

<span class="field-validation-error">You must specify a username.</span>

so if you aren't going to change this you're left to CSS and/or jQuery tricks to do the dirty work.

因此,如果你不打算改变它,那么你就可以使用CSS和/或jQuery技巧来完成这项肮脏的工作。

I'm not aware of a pure use if CSS to do your job, but if you can handle having your error message span within a DIV tag, you could try something like:

我不知道如果CSS可以完成你的工作,但是如果你可以处理你的错误消息跨越DIV标签,你可以尝试类似的东西:

.field-validation-error
{
    background: url(x.gif) no-repeat;
    padding-left:10px;
    color: #ff0000;
}

<div style="width:10px; height:10px; overflow:hidden;">
    <%= Html.ValidationMessage("username") %>
</div>

For a 10x10 gif, this will hide the text, but it will be within a block element and without your error message title/"tooltip." Not exactly the best solution. I would check the code for the ValidationMessage method in the MVC source and consider adapting your own to render it exactly as needed, or again, there's Javascript to do the trickery.

对于10x10 gif,这将隐藏文本,但它将在一个块元素内,并且没有错误消息title /“tooltip”。不完全是最好的解决方案。我会在MVC源代码中检查ValidationMessage方法的代码,并考虑根据需要调整自己的代码,或者再次使用Javascript来做诡计。

Edit: Just for fun I decided to test my own Validation Message helper, starting from the MVC source code. It's dirty (hard-coded path to image), but a working example. In this case it requires you to pass in the validation message - I've omitted some code where it optionally displays the default built-in message.

编辑:为了好玩,我决定从MVC源代码开始测试我自己的Validation Message助手。它很脏(硬编码的图像路径),但是一个工作的例子。在这种情况下,它需要您传递验证消息 - 我省略了一些代码,它可选地显示默认的内置消息。

public static string MyValidationMessage(this HtmlHelper htmlHelper, string modelName, string validationMessage)
{
    if (modelName == null)
        throw new ArgumentNullException("modelName");

    if (!htmlHelper.ViewData.ModelState.ContainsKey(modelName))
        return null;

    ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
    ModelErrorCollection modelErrors = (modelState == null) ? null : modelState.Errors;
    ModelError modelError = ((modelErrors == null) || (modelErrors.Count == 0)) ? null : modelErrors[0];

    if (modelError == null) 
        return null;

    return "<img src=\"../../Content/x.gif\" alt=\"Error\" title=\"" + validationMessage + "\" />";
}

#4


1  

Great answer by David Glenn. Many thanks for putting me on the right track with creating custom Html helpers in Mvc.

伟大的回答大卫格伦。非常感谢您通过在Mvc中创建自定义Html助手让我走上正轨。

But, there are a couple issues with David's extension out of the box (in MVC3 w/Razor):

但是,大卫的扩展开箱即用(在MVC3 w / Razor中)有几个问题:

  • Returning just a string will not work; it will actually display the string, tags and all, unless you wrap it on the view (UI) with MvcHtmlString.Create(). A more elegant approach is to change the return type of the helper function as an MvcHtmlString. You could also overload the Helper functions to accommodate both return types as well.

    只返回一个字符串是行不通的;它实际上会显示字符串,标签和所有内容,除非您使用MvcHtmlString.Create()将其包装在视图(UI)上。更优雅的方法是将辅助函数的返回类型更改为MvcHtmlString。您还可以重载Helper函数以适应两种返回类型。

  • If you are doing additional errors on a single model field, such as a RegEx check, etc., the helper method will fail because the initial "If..Then.." fails to check for an error count; just checking if it "Is Null" will not suffice. The Errors object will not be null, but all of it's properties will on the non-failing fields.

    如果您在单个模型字段上执行其他错误,例如RegEx检查等,则辅助方法将失败,因为初始“If..Then ..”无法检查错误计数;只是检查它是否“空”是不够的。 Errors对象不会为null,但所有属性都将在非失败字段上。

So below is the CustomHtmlHelper class refactored to accommodate for the above two issues and also injects the correct css class name:

以下是为重现上述两个问题而重构的CustomHtmlHelper类,并且还注入了正确的css类名:

#Region "Imports"

Imports System.Runtime.CompilerServices

#End Region

Namespace Laddawn.Web.Mvc.Extensions

    Public Module CustomHtmlHelpers

        <Extension()>
        Public Function ValidationImage(ByVal helper As HtmlHelper, ByVal name As String) As MvcHtmlString

            If helper.ViewData.ModelState(name) Is Nothing _
            OrElse helper.ViewData.ModelState(name).Errors Is Nothing _
            OrElse helper.ViewData.ModelState(name).Errors.Count = 0 Then
                Return MvcHtmlString.Empty
            End If

            Dim tag As New TagBuilder("img")

            With tag
                .Attributes.Add("src", "/Content/Images/Mobile/alert.png")
                .Attributes.Add("alt", helper.ViewData.ModelState(name).Errors(0).ErrorMessage)
                .Attributes.Add("title", helper.ViewData.ModelState(name).Errors(0).ErrorMessage)
                .Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName)
            End With

            Return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing))

        End Function

    End Module

End Namespace

In your Css file, create a class as such:

在您的Css文件中,创建一个类:

img.field-validation-error
{
    vertical-align:         text-bottom;
    margin-left:            5px;
}

Now your Css can manipulate the image separately from the massage css too.

现在你的Css也可以与按摩css分开操作图像。

Notes: Don't forget to change the image path to suit the needs of your project. This is another area where you could potentially add an additional parameter for imagePath and use a default in the helper method if one is not passed in.

注意:不要忘记更改图像路径以满足项目的需要。这是另一个可能为imagePath添加附加参数的区域,如果没有传入,则在helper方法中使用默认值。

Apologies for the VB version (for you C# developers), my current project is all VB/NET and if you want to use the above code, just use the converter over at Telerik (http://converter.telerik.com/)

对于VB版本(对于C#开发人员)抱歉,我当前的项目都是VB / NET,如果你想使用上面的代码,只需在Telerik上使用转换器(http://converter.telerik.com/)

#5


0  

Unfortunately, my custom validation image helper class will not work with client side validation.

不幸的是,我的自定义验证图像助手类不适用于客户端验证。

If anyone wants to take a crack at a version that can/will support client side validation, have at it!! :)

如果有人想破解能够/将支持客户端验证的版本,那么就拥有它! :)

#6


0  

Expanding on Ed's answer, this is so it can work with Models:

扩展Ed的答案,这是可以使用Models:

public static MvcHtmlString ValidationImageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        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;
        }

        TagBuilder tag = new TagBuilder("span");
        tag.Attributes.Add("class", "field-validation-error");
        tag.Attributes.Add("data-valmsg-for", name);
        tag.Attributes.Add("data-valmsg-replace", "true");
        return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing));
    }

I was rendering into a span.. the same way that MVC renders it. I have my background image set in the CSS class. Example:

我正在渲染成跨度......就像MVC渲染它一样。我在CSS类中设置了背景图像。例:

@Html.ValidationImageFor(x => x.FieldNameHere)

HTH

HTH

#7


0  

The best would be that MVC developers change the type of ModelError.ErrorMessage to an MvcHtmlString or its new counterpart in .NET4 (HtmlString)

最好的是MVC开发人员将ModelError.ErrorMessage的类型更改为MvcHtmlString或其在.NET4中的新对应项(HtmlString)

#1


13  

You can extend HtmlHelper like:

您可以扩展HtmlHelper,如:

public static class CustomHtmlHelper {

  public static string ValidationImage(this HtmlHelper helper, string name) {
    if (helper.ViewData.ModelState[name] == null || helper.ViewData.ModelState[name].Errors == null) {
      return String.Empty;
    }
    TagBuilder tag = new TagBuilder("img");
    tag.Attributes.Add("src", "Error.gif");
    tag.Attributes.Add("alt", "Error");
    tag.Attributes.Add("title", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
    return tag.ToString(TagRenderMode.SelfClosing);
  }

}

Then in your page import the class containing the extension method

然后在您的页面中导入包含扩展方法的类

<%@ Import Namespace="CustomHtmlHelperNamespace" %>

Then add the following to your page:

然后将以下内容添加到您的页面:

<label for="Name">Name:</label>
<%= Html.TextBox("Name")%>
<% Html.ValidationImage("Name") %>

For more on extending HtmlHelper try here but basically this extends HtmlHelper, checks the ViewState for a an error on the value parsed in name ("Name" in your case) and if it contains an error generates the HTML needed to render the image. The title attribute for the image will contain the validation message for field "Name"

有关扩展HtmlHelper的更多信息,请尝试此处,但基本上这会扩展HtmlHelper,检查ViewState是否在名称中解析的值上出现错误(在您的情况下为“Name”),如果包含错误,则生成呈现图像所需的HTML。图像的title属性将包含字段“Name”的验证消息

#2


1  

You can extend the Html Helper to add a method by making a class like below. Not 100% this is what you're asking, but here goes:

您可以扩展Html Helper以通过创建如下所示的类来添加方法。不是100%这是你要问的,但是这里是:

public class HtmlHelperExtensions {

    public static string GetMeSomething(this HtmlHelper helper)
    {
        //... Do things here. ...
    }
}

Once you have something like that, you can call Html.GetMeSomething, and it will return a string or whatever you declare your return type as.

一旦你有这样的东西,你可以调用Html.GetMeSomething,它将返回一个字符串或任何你声明你的返回类型为。

#3


1  

Rolling you own ValidationMessage helper to render an image tag may be your best bet... The built-in helper will render a tag such as

滚动你自己的ValidationMessage帮助器来渲染图像标签可能是你最好的选择......内置帮助器将渲染一个标签,如

<span class="field-validation-error">You must specify a username.</span>

so if you aren't going to change this you're left to CSS and/or jQuery tricks to do the dirty work.

因此,如果你不打算改变它,那么你就可以使用CSS和/或jQuery技巧来完成这项肮脏的工作。

I'm not aware of a pure use if CSS to do your job, but if you can handle having your error message span within a DIV tag, you could try something like:

我不知道如果CSS可以完成你的工作,但是如果你可以处理你的错误消息跨越DIV标签,你可以尝试类似的东西:

.field-validation-error
{
    background: url(x.gif) no-repeat;
    padding-left:10px;
    color: #ff0000;
}

<div style="width:10px; height:10px; overflow:hidden;">
    <%= Html.ValidationMessage("username") %>
</div>

For a 10x10 gif, this will hide the text, but it will be within a block element and without your error message title/"tooltip." Not exactly the best solution. I would check the code for the ValidationMessage method in the MVC source and consider adapting your own to render it exactly as needed, or again, there's Javascript to do the trickery.

对于10x10 gif,这将隐藏文本,但它将在一个块元素内,并且没有错误消息title /“tooltip”。不完全是最好的解决方案。我会在MVC源代码中检查ValidationMessage方法的代码,并考虑根据需要调整自己的代码,或者再次使用Javascript来做诡计。

Edit: Just for fun I decided to test my own Validation Message helper, starting from the MVC source code. It's dirty (hard-coded path to image), but a working example. In this case it requires you to pass in the validation message - I've omitted some code where it optionally displays the default built-in message.

编辑:为了好玩,我决定从MVC源代码开始测试我自己的Validation Message助手。它很脏(硬编码的图像路径),但是一个工作的例子。在这种情况下,它需要您传递验证消息 - 我省略了一些代码,它可选地显示默认的内置消息。

public static string MyValidationMessage(this HtmlHelper htmlHelper, string modelName, string validationMessage)
{
    if (modelName == null)
        throw new ArgumentNullException("modelName");

    if (!htmlHelper.ViewData.ModelState.ContainsKey(modelName))
        return null;

    ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
    ModelErrorCollection modelErrors = (modelState == null) ? null : modelState.Errors;
    ModelError modelError = ((modelErrors == null) || (modelErrors.Count == 0)) ? null : modelErrors[0];

    if (modelError == null) 
        return null;

    return "<img src=\"../../Content/x.gif\" alt=\"Error\" title=\"" + validationMessage + "\" />";
}

#4


1  

Great answer by David Glenn. Many thanks for putting me on the right track with creating custom Html helpers in Mvc.

伟大的回答大卫格伦。非常感谢您通过在Mvc中创建自定义Html助手让我走上正轨。

But, there are a couple issues with David's extension out of the box (in MVC3 w/Razor):

但是,大卫的扩展开箱即用(在MVC3 w / Razor中)有几个问题:

  • Returning just a string will not work; it will actually display the string, tags and all, unless you wrap it on the view (UI) with MvcHtmlString.Create(). A more elegant approach is to change the return type of the helper function as an MvcHtmlString. You could also overload the Helper functions to accommodate both return types as well.

    只返回一个字符串是行不通的;它实际上会显示字符串,标签和所有内容,除非您使用MvcHtmlString.Create()将其包装在视图(UI)上。更优雅的方法是将辅助函数的返回类型更改为MvcHtmlString。您还可以重载Helper函数以适应两种返回类型。

  • If you are doing additional errors on a single model field, such as a RegEx check, etc., the helper method will fail because the initial "If..Then.." fails to check for an error count; just checking if it "Is Null" will not suffice. The Errors object will not be null, but all of it's properties will on the non-failing fields.

    如果您在单个模型字段上执行其他错误,例如RegEx检查等,则辅助方法将失败,因为初始“If..Then ..”无法检查错误计数;只是检查它是否“空”是不够的。 Errors对象不会为null,但所有属性都将在非失败字段上。

So below is the CustomHtmlHelper class refactored to accommodate for the above two issues and also injects the correct css class name:

以下是为重现上述两个问题而重构的CustomHtmlHelper类,并且还注入了正确的css类名:

#Region "Imports"

Imports System.Runtime.CompilerServices

#End Region

Namespace Laddawn.Web.Mvc.Extensions

    Public Module CustomHtmlHelpers

        <Extension()>
        Public Function ValidationImage(ByVal helper As HtmlHelper, ByVal name As String) As MvcHtmlString

            If helper.ViewData.ModelState(name) Is Nothing _
            OrElse helper.ViewData.ModelState(name).Errors Is Nothing _
            OrElse helper.ViewData.ModelState(name).Errors.Count = 0 Then
                Return MvcHtmlString.Empty
            End If

            Dim tag As New TagBuilder("img")

            With tag
                .Attributes.Add("src", "/Content/Images/Mobile/alert.png")
                .Attributes.Add("alt", helper.ViewData.ModelState(name).Errors(0).ErrorMessage)
                .Attributes.Add("title", helper.ViewData.ModelState(name).Errors(0).ErrorMessage)
                .Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName)
            End With

            Return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing))

        End Function

    End Module

End Namespace

In your Css file, create a class as such:

在您的Css文件中,创建一个类:

img.field-validation-error
{
    vertical-align:         text-bottom;
    margin-left:            5px;
}

Now your Css can manipulate the image separately from the massage css too.

现在你的Css也可以与按摩css分开操作图像。

Notes: Don't forget to change the image path to suit the needs of your project. This is another area where you could potentially add an additional parameter for imagePath and use a default in the helper method if one is not passed in.

注意:不要忘记更改图像路径以满足项目的需要。这是另一个可能为imagePath添加附加参数的区域,如果没有传入,则在helper方法中使用默认值。

Apologies for the VB version (for you C# developers), my current project is all VB/NET and if you want to use the above code, just use the converter over at Telerik (http://converter.telerik.com/)

对于VB版本(对于C#开发人员)抱歉,我当前的项目都是VB / NET,如果你想使用上面的代码,只需在Telerik上使用转换器(http://converter.telerik.com/)

#5


0  

Unfortunately, my custom validation image helper class will not work with client side validation.

不幸的是,我的自定义验证图像助手类不适用于客户端验证。

If anyone wants to take a crack at a version that can/will support client side validation, have at it!! :)

如果有人想破解能够/将支持客户端验证的版本,那么就拥有它! :)

#6


0  

Expanding on Ed's answer, this is so it can work with Models:

扩展Ed的答案,这是可以使用Models:

public static MvcHtmlString ValidationImageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        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;
        }

        TagBuilder tag = new TagBuilder("span");
        tag.Attributes.Add("class", "field-validation-error");
        tag.Attributes.Add("data-valmsg-for", name);
        tag.Attributes.Add("data-valmsg-replace", "true");
        return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing));
    }

I was rendering into a span.. the same way that MVC renders it. I have my background image set in the CSS class. Example:

我正在渲染成跨度......就像MVC渲染它一样。我在CSS类中设置了背景图像。例:

@Html.ValidationImageFor(x => x.FieldNameHere)

HTH

HTH

#7


0  

The best would be that MVC developers change the type of ModelError.ErrorMessage to an MvcHtmlString or its new counterpart in .NET4 (HtmlString)

最好的是MVC开发人员将ModelError.ErrorMessage的类型更改为MvcHtmlString或其在.NET4中的新对应项(HtmlString)