4

How can I use resources from a different assembly to override the default attribute error messages in my MVC5 application?

My website is namespaced: Company.Web

My resources assembly is namespaced: Company.Web.Resources

I can easily localize attribute error messages individually using:

[Required(ErrorMessageResourceName = "PropertyValueRequired", ErrorMessageResourceType = typeof(Company.Web.Resources.Messages))]

However, since our error message is always "Required", I'd simply like to put the [Required] attribute without having to specify the resource name. I'd also like to override the default data type messages output by MVC which you can't do via an attribute.

The field {0} must be a date.

I'd like to be

Invalid date

I've seen examples where you can put the resource files in App_GlobalResources (with keys PropertyValueRequired, FieldMustBeDate, FieldMustBeNumeric) and setting ClientDataTypeModelValidatorProvider.ResourceClassKey, but I already have an external resources assembly I want to use.

I've tried using the following in my Global.asax with no luck:

ClientDataTypeModelValidatorProvider.ResourceClassKey = "Company.Web.Resources.Messages"

How can I accomplish this? Any ideas?

UPDATE (Partial Resolution)

I can solve my attribute-based problem simply by creating new validation adapters and using them in lieu of the default:

public class MyRequiredAttributeAdapter : RequiredAttributeAdapter
{
    public MyRequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute)
        : base(metadata, context, attribute)
    {
        if (attribute.ErrorMessage.IsNullOrWhitespace() 
            && attribute.ErrorMessageResourceName.IsNullOrWhitespace() 
            && attribute.ErrorMessageResourceType == null)
        {
            attribute.ErrorMessageResourceType = typeof (Resources.Validation.Messages);
            attribute.ErrorMessageResourceName = "PropertyValueRequired";
        }
    }
}

Global.asax

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredAttribute), typeof(MyRequiredAttributeAdapter));

However, this still leaves me scratching my head on how to override the default data type message for non-null properties such as DateTime and int. Also, I believe there are some I am unable to override because they are internal (DataTypeAttributeAdapter, CompareAttributeAdapter).

6
  • Couldn't you just create your own attributes inheriting the built in attributes? Commented Aug 1, 2014 at 17:23
  • Yes, unfortunately that doesn't handle the built-in data type validation for dates and numbers. For example, when you have a non-nullable DateTime property on a model (without using any attributes at all), the message output is "The field {0} must be a date.". I want it to say "Invalid Date". Commented Aug 1, 2014 at 17:32
  • possible duplicate of How to change default validation error message in ASP.NET MVC? Commented Aug 1, 2014 at 18:16
  • Not a duplicate. All those solutions rely on resources created within the same web assembly using App_GlobalResources. My resource strings need to derive from another assembly. Commented Aug 1, 2014 at 18:35
  • Did you manage to find a full solution to this? I have the same issue. Commented Mar 30, 2015 at 3:45

2 Answers 2

1

This might be quite late, but then here is a solution that should work based primarily on the logic behind your partial solution.

  1. Implement a custom RequiredAttribute for your project

    public class MyRequiredAttribute : RequiredAttribute
    {
        //Your custom code
    }
    
  2. Modify your MyRequiredAttributeAdapter code as shown. Notice that you now need to inherit from the generic DataAnnotationsModelValidator class, which allows you pass in your custom MyRequiredAttribute

    public class MyRequiredAttributeAdapter : DataAnnotationsModelValidator<MyRequiredAttribute>
    {
        public MyRequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, MyRequiredAttribute attribute)
            : base(metadata, context, attribute)
        {
            if (string.IsNullOrWhiteSpace(attribute.ErrorMessage)
                && string.IsNullOrWhiteSpace(attribute.ErrorMessageResourceName)
                && attribute.ErrorMessageResourceType == null)
            {
                attribute.ErrorMessageResourceType = typeof(Resources.Validation.Messages);
                attribute.ErrorMessageResourceName = "PropertyValueRequired";
            }
        }
    }
    
  3. Add this to Global.asax (modified from what you have in your partial solution)

    DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyRequiredAttribute), typeof(MyRequiredAttributeAdapter));
    
Sign up to request clarification or add additional context in comments.

Comments

0

To override the default data type message for non-null properties such as DateTime and int,
implement an own MyClientDataTypeModelValidatorProvider based on the MVC ClientDataTypeModelValidatorProvider.
Add that instance to ModelValidatorProviders.Providers, and removed the default one.

So, put this into Global.asax:

var clientDataTypeModelValidatorProviderIndex = ModelValidatorProviders.Providers.FindIndex(modelValidatorProvider => modelValidatorProvider is ClientDataTypeModelValidatorProvider);
ModelValidatorProviders.Providers.RemoveAt(clientDataTypeModelValidatorProviderIndex);
ModelValidatorProviders.Providers.Add(new MyClientDataTypeModelValidatorProvider());

Tested with MVC 5

Comments

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.