How to prevent MVC3 html leak in my validation messages?

I am trying to display a validation message in MVC3 that contains a link.

I displayed a place holder with an error message like this

@Html.ValidationMessageFor(model => model.Email)

The problem is that the error message is html escaped, which is fine in most cases, but I want the link in the middle.

<span class="field-validation-error" data-valmsg-for="Email" data-valmsg-replace="true">This e-mail address is already registed. &lt;a href=&quot;%url_token%&quot;&gt;Click here to reset.&lt;/a&gt;</span>

How can I prevent this?

It works, but it’s not a solution, but a temporary job.

@{
  string s = Html.ValidationMessageFor(model => model.Email).ToString();
}
@Html.Raw(HttpUtility.HtmlDecode(s))
+5
source share
2 answers

Taking @BrunoLM, the following extension methods should give you what you need. I just did some basic testing, but it works.

public static class HtmlHelperExtensions
{
    private static readonly string htmlErrorPlaceholder = "##__html#Error#Placeholder__##";

    public static IHtmlString HtmlValidationMessageFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        object htmlAttributes)
        {
            var name      = expression.GetMemberName();
            var isInError = htmlHelper.ViewContext.ViewData.ModelState.ContainsKey(name);
            var message   = htmlHelper.ValidationMessageFor(expression, htmlErrorPlaceholder, htmlAttributes);
            if (isInError && !MvcHtmlString.IsNullOrEmpty(message))
            {
                var realError = htmlHelper.ViewContext.ViewData.ModelState[name].Errors.First().ErrorMessage;
                return htmlHelper.Raw(message.ToString().Replace(htmlErrorPlaceholder, realError));
            }

            return MvcHtmlString.Empty;
        }
}

public static class Expression_1Extensions
{
    public static string GetMemberName<TModel, TProperty>(this Expression<Func<TModel, TProperty>> expression)
    {
        switch (expression.Body.NodeType)
        {
            case ExpressionType.MemberAccess:
                MemberExpression memberExpression = (MemberExpression)expression.Body;
                return memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
        }

        throw new NotSupportedException();
    }
}
0
source

Looking at the code with a reflector, it doesn't seem to have a method, a more complete overload:

public static MvcHtmlString ValidationMessageFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    string validationMessage,
    object htmlAttributes)
{
    return htmlHelper.ValidationMessageFor<TModel, TProperty>(expression, validationMessage, ((IDictionary<string, object>) HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)));
}

, , :

public static class ValidationExtender
{
    public static IHtmlString HtmlValidationMessageFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression)
    {
        return MvcHtmlString.Create(htmlHelper.ValidationMessageFor(expression).ToHtmlString());
    }
}

MvcHtmlString. . MvcHtmlString.Create(). html .

+1

All Articles