Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8035353
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 5, 20262026-06-05T02:17:05+00:00 2026-06-05T02:17:05+00:00

Coming from the asp.net webforms model I’m used to using validators which display an

  • 0

Coming from the asp.net webforms model I’m used to using validators which display an error in the form <span title="Username is Required">*</span>.

I’m quite clear how the MVC3 validators work out of the box, so please no more answers explaining how validators work in MVC3 as I’m pretty sure I have that nailed. What I am trying to accomplish is have the validation error message showing as the title of the span tag as shown in the first paragraph.

I have managed to replicate this in MVC3 but am not sure if the way I have done it follows best practise. I would appreciate any input as to whether there is a better way to accomplish the same thing. It would be really great if it could be done without modifying jquery.validate.unobtrusive.js.

So what I have done is:

  1. Set the validation message to “*”
  2. Hidden the validation message while its valid
  3. Added a new attribute to determine whether to add the message as the title
  4. Added 2 lines of flagged code to onError to check whether to display the error message in the title, and if so to do so.
    [.cshtml]    @Html.ValidationMessageFor(m => m.Email, "*", new { data_val_usetitle = "true" })

    [.css]    .field-validation-valid {display:none;}

    .js]        function onError(error, inputElement) {  // 'this' is the form element
                var container = $(this).find("[data-valmsg-for='" + inputElement[0].name + "']"),
                    replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false,
                    useTitle = $.parseJSON(container.attr("data-val-usetitle")) !== false; /* New Line */

                container.removeClass("field-validation-valid").addClass("field-validation-error");
                error.data("unobtrusiveContainer", container);

                if (replace) {
                    container.empty();
                    error.removeClass("input-validation-error").appendTo(container);
                }
                else {
                    if (useTitle) container.attr("title", error.text()); /* New Line */
                    error.hide();
                }
            }
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-05T02:17:06+00:00Added an answer on June 5, 2026 at 2:17 am

    I think what you’ve done is the cleanest way. There is no way around modifying jquery.validate.unobtrusive.js because MVC extensions don’t follow the old school asp.net methodology of emitting javascript on the fly.

    I just finished creating my own custom validation extension calld ValidationIconFor() so that a single image is displayed with its title set to the error message and I’ve used a modified version of your code above.

    jquery.validate.unobtrusive.js:

    function onError(error, inputElement) {  // 'this' is the form element
        var container = $(this).find("[data-valmsg-for='" + inputElement[0].name + "']"),
            replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false,
            useTitle = $.parseJSON(container.attr("data-val-usetitle")) !== false;
    
        container.removeClass("field-validation-valid").addClass("field-validation-error");
        error.data("unobtrusiveContainer", container);
    
        if (replace) {
            container.empty();
            if (useTitle)
                container.attr("title", error.text());
            else
                error.removeClass("input-validation-error").appendTo(container);
        }
        else {
            if (useTitle)
                container.attr("title", error.text());
            error.hide();
        }
    }
    

    ValidationExtensions.cs:

    public static class ValidationExtensions
    {
        private static string _resourceClassKey;
    
        public static string ResourceClassKey
        {
            get
            {
                return _resourceClassKey ?? String.Empty;
            }
            set
            {
                _resourceClassKey = value;
            }
        }
    
        private static FieldValidationMetadata ApplyFieldValidationMetadata(HtmlHelper htmlHelper, ModelMetadata modelMetadata, string modelName)
        {
            FormContext formContext = htmlHelper.ViewContext.FormContext;
            FieldValidationMetadata fieldMetadata = formContext.GetValidationMetadataForField(modelName, true /* createIfNotFound */);
    
            // write rules to context object
            IEnumerable<ModelValidator> validators = ModelValidatorProviders.Providers.GetValidators(modelMetadata, htmlHelper.ViewContext);
            foreach (ModelClientValidationRule rule in validators.SelectMany(v => v.GetClientValidationRules()))
            {
                fieldMetadata.ValidationRules.Add(rule);
            }
    
            return fieldMetadata;
        }
    
        private static string GetInvalidPropertyValueResource(HttpContextBase httpContext)
        {
            string resourceValue = null;
            if (!String.IsNullOrEmpty(ResourceClassKey) && (httpContext != null))
            {
                // If the user specified a ResourceClassKey try to load the resource they specified.
                // If the class key is invalid, an exception will be thrown.
                // If the class key is valid but the resource is not found, it returns null, in which
                // case it will fall back to the MVC default error message.
                resourceValue = httpContext.GetGlobalResourceObject(ResourceClassKey, "InvalidPropertyValue", CultureInfo.CurrentUICulture) as string;
            }
            return resourceValue ?? "The value '{0}' is invalid.";
        }
    
        private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState)
        {
            if (!String.IsNullOrEmpty(error.ErrorMessage))
            {
                return error.ErrorMessage;
            }
            if (modelState == null)
            {
                return null;
            }
    
            string attemptedValue = (modelState.Value != null) ? modelState.Value.AttemptedValue : null;
            return String.Format(CultureInfo.CurrentCulture, GetInvalidPropertyValueResource(httpContext), attemptedValue);
        }
    
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString ValidationIconFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return ValidationIconFor(htmlHelper, expression, null /* validationMessage */, new RouteValueDictionary());
        }
    
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString ValidationIconFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string validationMessage)
        {
            return ValidationIconFor(htmlHelper, expression, validationMessage, new RouteValueDictionary());
        }
    
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString ValidationIconFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string validationMessage, object htmlAttributes)
        {
            return ValidationIconFor(htmlHelper, expression, validationMessage, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
    
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString ValidationIconFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string validationMessage, IDictionary<string, object> htmlAttributes)
        {
            return ValidationMessageHelper(htmlHelper,
                                           ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData),
                                           ExpressionHelper.GetExpressionText(expression),
                                           validationMessage,
                                           htmlAttributes);
        }
    
        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "Normalization to lowercase is a common requirement for JavaScript and HTML values")]
        private static MvcHtmlString ValidationMessageHelper(this HtmlHelper htmlHelper, ModelMetadata modelMetadata, string expression, string validationMessage, IDictionary<string, object> htmlAttributes)
        {
            string modelName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression);
            FormContext formContext = htmlHelper.ViewContext.FormContext;
    
            if (!htmlHelper.ViewData.ModelState.ContainsKey(modelName) && formContext == null)
            {
                return null;
            }
    
            ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
            ModelErrorCollection modelErrors = (modelState == null) ? null : modelState.Errors;
            ModelError modelError = (((modelErrors == null) || (modelErrors.Count == 0)) ? null : modelErrors.FirstOrDefault(m => !String.IsNullOrEmpty(m.ErrorMessage)) ?? modelErrors[0]);
    
            if (modelError == null && formContext == null)
            {
                return null;
            }
    
            TagBuilder builder = new TagBuilder("img");
            builder.MergeAttributes(htmlAttributes);
            builder.AddCssClass((modelError != null) ? HtmlHelper.ValidationMessageCssClassName : HtmlHelper.ValidationMessageValidCssClassName);
    
            if (!String.IsNullOrEmpty(validationMessage))
            {
                builder.Attributes.Add("title", validationMessage);
            }
            else if (modelError != null)
            {
                builder.Attributes.Add("title", GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, modelState));
            }
    
            if (formContext != null)
            {
                bool replaceValidationMessageContents = String.IsNullOrEmpty(validationMessage);
    
                if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled)
                {
                    builder.MergeAttribute("data-valmsg-for", modelName);
                    builder.MergeAttribute("data-valmsg-replace", replaceValidationMessageContents.ToString().ToLowerInvariant());
                    builder.MergeAttribute("data-val-usetitle", "true");
                }
                else
                {
                    FieldValidationMetadata fieldMetadata = ApplyFieldValidationMetadata(htmlHelper, modelMetadata, modelName);
                    // rules will already have been written to the metadata object
                    fieldMetadata.ReplaceValidationMessageContents = replaceValidationMessageContents; // only replace contents if no explicit message was specified
    
                    // client validation always requires an ID
                    builder.GenerateId(modelName + "_validationMessage");
                    fieldMetadata.ValidationMessageId = builder.Attributes["id"];
                }
            }
    
            return builder.ToMvcHtmlString(TagRenderMode.Normal);
        }
    }
    
    internal static class TagBuilderExtensions
    {
        internal static MvcHtmlString ToMvcHtmlString(this TagBuilder tagBuilder, TagRenderMode renderMode)
        {
            return new MvcHtmlString(tagBuilder.ToString(renderMode));
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm coming from a ASP.NET Webforms application. I'm using a third party control from
I just started ASP.NET MVC (coming from WebForms) and I'm struggling with some really
I'm using an checkbox on an ASP.NET MVC form like so: <%=Html.CheckBox(AgreeToRules, Model.AgreeToRules)%> The
I have a string (coming from ASP.NET) which contains one or more placeholders. In
I am trying to learn web development using Mono. Coming from ASP.NET background, I
Coming from ASP.NET into WindowsForms app development I was expecting to see the similar
I have wanted to try GAE since launch, but coming from ASP .NET and
I'm trying to understand ColdFusion, as I am coming from ASP.NET. I've put together
Coming from ASP.NET I'm having a hard time with basic ADF concepts. I need
I'm keen to teach myself ASP.NET MVC 2 (coming from a heavy embedded or

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.