Mou
Mou

Reputation: 16282

How to insert custom error message from server side validation attribute

I am working with a custom validation attribute and want to show my validation message, where I will specify a name like this:

return new ValidationResult(FormatErrorMessage("Hobbies"));

I found this html was there on the page:

<span data-valmsg-replace="true" data-valmsg-for="Hobbies" class="field-validation-valid text-danger"></span>

When I return message from the IsValid function of the ValidationAttribute class like this:

return new ValidationResult(FormatErrorMessage("Hobbies"));

Where I specify the name "Hobbies" then it should be added into

<span data-valmsg-for="Hobbies">

Why was my error message was not added?

If you want me to paste full code then please tell me.

Upvotes: 1

Views: 4857

Answers (1)

Kevin Nelson
Kevin Nelson

Reputation: 7663

I apologize, I'm not completely sure about your question. However, since you said "give me a clue what kind of mistake I have done," I'm going to go with explaining the approach that I've taken in a project which utilizes the ViewModel and a couple of custom validation-handling methods.

I don't think this is a direct answer to your question, but it should give you enough information to be able to make custom methods that build the HTML with the error message content inside it the way you want if you are using MVC w/ razor.

Utilizing ViewModels in razor for validation

Normally, with .NET MVC razor (you didn't mention which version of MVC you were using), you just utilize attributes in the view model for validation, e.g.

public class MyViewModel {
    [Required(ErrorMessage = "Required")]
    public string Name {get; set;}
}

These automatically get validated on post. This will set the property of the view model "Name" to required, and when the validation fails, the error message will be "Required."

Now, if you are doing some processing server side and doing complex validation that is not easy to setup in attributes, then you can manually add an error to your model, like so (my code for captcha validation):

//inside controller HttpPost method
var isCaptchaValid = ReCaptcha.IsCaptchaValid(Request.Form["g-recaptcha-response"] ?? "");
if (!isCaptchaValid)
{
    ModelState.AddModelError("Captcha", "Verification Required");
}

Where "Captcha" is the field name and "Verification Required" is the error message.

Displaying Custom Error Messages

Then, stepping away from the standard approach, I have some classes that will build the Bootstrap 3 class "has-error" for the form-group and a custom error that wraps the error message in a label:

public static class HtmlExtensions {
    public static string GetErrorClass(this HtmlHelper htmlHelper, bool hasError)
    {
        return " has-error";
    }
    public static MvcHtmlString ErrorLabel<TModel>(this HtmlHelper<TModel> helper, ModelStateDictionary modelState, string fieldName)
    {
        if (modelState[fieldName] != null )
        {
            var error = modelState[fieldName].Errors.FirstOrDefault();
            if (error != null)
            {
                var span = new TagBuilder("span");
                span.AddCssClass("label label-danger");
                span.InnerHtml = error.ErrorMessage;
                return MvcHtmlString.Create(span.ToString(TagRenderMode.Normal));
            }
        }
        return MvcHtmlString.Empty;
    }
}

From there, you can use it just like any of the other @Html

<div class='[email protected]("Name")'>
    <label class='control-label col-xs-12 col-sm-6' for='name'>@Html.ErrorLabel(ViewData.ModelState,"Name") Name:</label>
    <div class='col-xs-12 col-sm-6'>
        @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
    </div>
</div>

Anyway, I hope that helps you with what you are trying to do. If this is so far away from an answer to your problem, please let me know and I'll remove the answer.

Applying to your HTML requirements:

Oh, and I guess to build the HTML the way you are wanting to, doing it this way, the extension method would look like this:

public static MvcHtmlString MyErrorExtension<TModel>(this HtmlHelper<TModel> helper, ModelStateDictionary modelState, string fieldName)
{
    if (modelState[fieldName] != null)
    {
        var error = modelState[fieldName].Errors.FirstOrDefault();

        //<span data-valmsg-replace="true" data-valmsg-for="Hobbies" class="field-validation-valid text-danger"></span>
        var span = new TagBuilder("span");
        span.Attributes.Add("data-valmsg-replace", "true");
        span.Attributes.Add("data-valmsg-for", fieldName);
        span.AddCssClass("field-validation-valid text-danger");

        if (error != null)
        {
            span.InnerHtml = error.ErrorMessage;
        }
        return MvcHtmlString.Create(span.ToString(TagRenderMode.Normal));
    }
    return MvcHtmlString.Empty;
}

The above method will create your tag regardless, and it will populate it with the first error it finds if there are any errors for that field name.

Upvotes: 5

Related Questions