IEnumerator
IEnumerator

Reputation: 2972

ModelState.AddModelError encodes HTML

I am noticing a weird issue when using ModelState.AddModelError to validate input on my forms. The output from Html.ValidationMessage is not the true HTML value but it's encoded value and so the CSS style is not applied to the error message.

Example:

private string errorMessage = "<span class=\"negative\">{0}</span><br class=\"hid\" />";
ModelState.AddModelError("title", String.Format(errorMessage, "Tab title is required"));

The output is shown as:

<span class="field-validation-error">&lt;span class=&quot;negative&quot;&gt;URL is Required&lt;/span&gt;&lt;br class=&quot;hid&quot; /&gt;</span>

This didn't use to be the case with their earlier beta's and I am not sure what approach to take here.

Thanks Nick

Upvotes: 16

Views: 12335

Answers (3)

Stephen Murumba
Stephen Murumba

Reputation: 549

With the advent of several changes in .NET, we query ModelState values for errors using the relevant key. Using this approach you don't have to decode any string you pass using ModelState.AddModelError

@{
    var state = ModelState.FirstOrDefault(x => x.Key.Equals("title"));
    var error = state.Value != null &&
        state.Value.Errors.Any(x => !string.IsNullOrEmpty(x.ErrorMessage))
        ? state.Value.Errors.LastOrDefault()
        : null;
}
@if (error != null)
{
    <span>@Html.Raw(error.ErrorMessage)</span>
}

Here is an extension for the same

using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace Microsoft.AspNetCore.Mvc

public static class ModelStateDictionaryExtensions
{
    public static string GetError(this ModelStateDictionary modelState, string key)
    {
        var state = modelState.FirstOrDefault(x => x.Key.Equals(key));
        var error = state.Value != null && 
            state.Value.Errors.Any(x => !string.IsNullOrEmpty(x.ErrorMessage))
            ? state.Value.Errors.LastOrDefault()
            : null;
        return error?.ErrorMessage;
    }
}

The usage would be:

@{
    var errorTitle = ModelState.GetError("title");
}
@if (!string.IsNullOrEmpty(errorTitle))
{
    <span>@Html.Raw(errorTitle)</span>
}

Upvotes: 0

Roshan
Roshan

Reputation: 164

There is another way to do it, too, without having to create your own extension.

Say for instance we have the following in one of our controllers:

ModelState.AddModelError("Name", "<b>Please Use a Valid Person Name</b>");

We can then do the following in our view:

@if(Html.ValidationMessageFor(x => x.Name) != null){
    @Html.Raw(Html.ValidationMessageFor(x => x.Name).ToString())
}

The will prevent the error message of '<b>Please Use a Valid Person Name</b>' from being encoded.

Upvotes: 14

ten5peed
ten5peed

Reputation: 15890

Create your own extension method that mimics Html.VallidationMessage...?

I had to do something similar because the built in MVC validation stuff (ModelState, ValidationMessage etc etc) doesn't cater for pages that have more than one form on a page.

Upvotes: 0

Related Questions