1

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.

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

7 Comments

this line return new ValidationResult(FormatErrorMessage("Hobbies")); return error from isValid function of validation attribute and i thought if i mention name then validation message will appear there. but nothing comes......i definitely mistake something.
@Html.ErrorLabel is any custom helper function or inbuilt ?
@Mou, That's an extension method. I just posted at the very bottom an example extension method that would build the tag the way that you want. Extension methods must be in a STATIC class, BTW...you can't just stick it anywhere.
@Mou, if you use the ViewModel approach in MVC razor, your ValidationResults are automatically placed in your model, so you don't need to return them. Are you using MVC razor or an older version of MVC?
@Mou, sorry I realized my method for applying it to your HTML wouldn't output the HTML at all unless there was an error. However, since it appears you are using client-side validation, you need the tag to exist even when there is no error. So, I fixed that and the tag will always be there for a fieldName that exists in the view model.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.