18

In the world of MVC I have this view model...

public class MyViewModel{

[Required]
public string FirstName{ get; set; }    }

...and this sort of thing in my view...

<%= Html.ValidationSummary("Please correct the errors and try again.") %>
<%= Html.TextBox("FirstName") %>
<%= Html.ValidationMessage("FirstName", "*") %>

My question: If I submit this form without supplying a name, I get the following message "The FirstName field is required"

OK. So, I go and change my property to...

[DisplayName("First Name")]
[Required]
public string FirstName{ get; set; }    

..and now get "The First Name field is required"

All good so far.

So now I want the error message to display "First Name Blah Blah". How can I override the default message to display DisplayName + " Blah Blah", wihtout annotating all the properties with something like

[Required(ErrorMessage = "First Name Blah Blah")]

Cheers,

ETFairfax

tereško
  • 58,060
  • 25
  • 98
  • 150
ETFairfax
  • 3,794
  • 8
  • 40
  • 58
  • Please refer the below link: https://stackoverflow.com/questions/53042131/how-to-override-default-required-error-message/58543227#58543227 – VCody Oct 24 '19 at 14:11

8 Answers8

16
public class GenericRequired: RequiredAttribute
{
    public GenericRequired()
    {
        this.ErrorMessage = "{0} Blah blah"; 
    }
}
ckarbass
  • 3,651
  • 7
  • 34
  • 43
  • great solution, and very simple. Thanks! – mateuscb Oct 04 '11 at 22:15
  • 1
    but why is it when i override the behaviour of the default Required attribute that a post occurs so that the login form error message appears in addition to the field validators; whereas when using the default required attribute, just the field validator message is shown? – topwik Nov 28 '11 at 15:02
  • 1
    Chad's solution works great for me also removing the message from "Invalid User or Password". – Rafael A. M. S. Jan 22 '14 at 15:45
  • 3
    **It will break jQuery Validation Unobtrusive.** – Serg Mar 02 '18 at 19:19
13

Here is a way to do it without subclassing RequiredAttribute. Just make some attribute adapter classes. Here I'm using ErrorMessageResourceType/ErrorMessageResourceName (with a resource) but you could easily set ErrorMessage, or even check for the existence of overrides before setting these.

Global.asax.cs:

public class MvcApplication : HttpApplication {
    protected void Application_Start() {
        // other stuff here ...
        DataAnnotationsModelValidatorProvider.RegisterAdapter(
            typeof(RequiredAttribute), typeof(CustomRequiredAttributeAdapter));
        DataAnnotationsModelValidatorProvider.RegisterAdapter(
            typeof(StringLengthAttribute), typeof(CustomStringLengthAttributeAdapter));
    }
}

private class CustomRequiredAttributeAdapter : RequiredAttributeAdapter {
    public CustomRequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute)
        : base(metadata, context, attribute)
    {
        attribute.ErrorMessageResourceType = typeof(Resources);
        attribute.ErrorMessageResourceName = "ValRequired";
    }
}

private class CustomStringLengthAttributeAdapter : StringLengthAttributeAdapter {
    public CustomStringLengthAttributeAdapter(ModelMetadata metadata, ControllerContext context, StringLengthAttribute attribute)
        : base(metadata, context, attribute)
    {
        attribute.ErrorMessageResourceType = typeof(Resources);
        attribute.ErrorMessageResourceName = "ValStringLength";
    }
}

This example would have you create a resource file named Resources.resx with ValRequired as the new required default message and ValStringLength as the string length exceeded default message. Note that for both, {0} receives the name of the field, which you can set with [Display(Name = "Field Name")].

Anthony Mills
  • 8,676
  • 4
  • 32
  • 51
  • But how about the "must be numeric" some error like that?? – qakmak Oct 09 '14 at 19:44
  • I first thought this wouldn't work if the validation is done server side, but after testing it appears to work, at least when validation is done through MVC – Jeff Walker Code Ranger Nov 20 '14 at 17:26
  • This basically registers something to be run every time it sees an attribute of those types on model metadata. It just changes the default configuration of validation attributes. You don't have to use a special attribute or anything like that. – Anthony Mills Nov 27 '14 at 21:26
  • This doesn't need a resource file. You can directly assign using `attribute.ErrorMessage = "This field is required.";` –  Aug 27 '15 at 09:34
  • Yes, as I noted in the first paragraph. :) – Anthony Mills Mar 17 '16 at 17:08
13

It seems that RequiredAttribute doesn't implement IClientValidatable, so if you override the RequiredAttribute it breaks client side validation.

So this is what I did and it works. Hope this helps someone.

public class CustomRequiredAttribute : RequiredAttribute, IClientValidatable
{
    public CustomRequiredAttribute()
    {
        this.ErrorMessage = "whatever your error message is";
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessage,
            ValidationType = "required"
        };
    }
}
Chad
  • 1,404
  • 1
  • 18
  • 29
1

Edit: I posted this because I was looking for this solution with [Required] attribute and had problem to find it. Creating new Q/A don't look that good, since this question already exists.

I was trying to solve the same thing and I found very simple solution in MVC 4.

First, you would probably have to store error messages in some place. I used custom resources, well described at http://afana.me/post/aspnet-mvc-internationalization.aspx.

Important is, that I can get any resource (even error message) by simply calling ResourcesProject.Resources.SomeCustomError or ResourcesProject.Resources.MainPageTitle etc. Everytime I try to access Resources class, it takes culture info from current thread and returns right language.

I have error message for field validation in ResourcesProject.Resources.RequiredAttribute. To set this message to appear in View, simply update [Required] attribute with these two parameters.

ErrorMessageResourceType - Type which will be called (in our example ResourcesProject.Resources)

ErrorMessageResourceName - Property, which will be called on the type above (In our case RequiredAttribute)

Here is a very simplified login model, which shows only username validation message. When the field is empty, it will take the string from ResourcesProject.Resources.RequiredAttribute and display this as an error.

    public class LoginModel
    {        
        [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName="RequiredAttribute")]
        [Display(Name = "User name")]
        public string UserName { get; set; }
}
Martin Brabec
  • 3,720
  • 2
  • 23
  • 26
1

Just change

[Required] 

to

[Required(ErrorMessage = "Your Message, Bla bla bla aaa!")]
Phien
  • 148
  • 1
  • 14
0

You can write your own attribute:

public class MyRequiredAttribute : ValidationAttribute
{
    MyRequiredAttribute() : base(() => "{0} blah blah blah blaaaaaah")
    {

    }

    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return false;
        }
        string str = value as string;
        if (str != null)
        {
            return (str.Trim().Length != 0);
        }
        return true;
    }
}

This is copy of RequiredAttribute from Reflector with changed error message.

LukLed
  • 31,452
  • 17
  • 82
  • 107
  • why is it when i override the behaviour of the default Required attribute that a post back seems to have to occur so that the login form error message appears in addition to the field validators; whereas when using the default required attribute, just the field validator message is shown? – topwik Nov 28 '11 at 14:57
  • @towpse: If I understood you correctly, this is related to jquery validation working with Required attribute and not working with new one. – LukLed Nov 28 '11 at 16:01
0
using Resources;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Web;
using System.Web.Mvc;

public class CustomRequiredAttribute : RequiredAttribute,  IClientValidatable
{
    public CustomRequiredAttribute()
    {
        ErrorMessageResourceType = typeof(ValidationResource);
        ErrorMessageResourceName = "RequiredErrorMessage";
    }


    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {


        yield return new ModelClientValidationRule
        {
            ErrorMessage = GetRequiredMessage(metadata.DisplayName),
            ValidationType = "required"
        };
    }


    private string GetRequiredMessage(string displayName) {

        return displayName + " " + Resources.ValidationResource.RequiredErrorMessageClient;        

    }


}

App_GlobalResources/ValidationResource.resx

enter image description here

Now use data annotation

[CustomRequired]
Pascal Carmoni
  • 554
  • 4
  • 8
-1

This worked for me. Carefully read the comments inside the code. (Based on Chad's answer).

 // Keep the name the same as the original, it helps trigger the original javascript 
 // function for client side validation.

        public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute, IClientValidatable
            {
                public RequiredAttribute()
                {
                    this.ErrorMessage = "Message" // doesnt get called again. only once.
                }

                public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
                {
                    yield return new ModelClientValidationRule
                    {
                        ErrorMessage = "Message", // this gets called on every request, so it's contents can be dynamic.
                        ValidationType = "required"
                    };
                }
            }
Jeroen
  • 4,023
  • 2
  • 24
  • 40
  • 2
    You really shouldn't copy someone's answer. If you have something to add, you should bring it up in the answer's comments. – JustinP8 Apr 11 '12 at 14:50