views:

114

answers:

1

I have a required attribute that used with resources:

public class ArticleInput : InputBase
{
    [Required(ErrorMessageResourceType = typeof(ArticleResources), ErrorMessageResourceName = "Body_Validation_Required")]
    public string Body { get; set; }
}

I want to specify the resources be convention, like this:

public class ArticleInput : InputBase
{
    [Required2]
    public string Body { get; set; }
}

Basically, Required2 implements the values based on this data:

ErrorMessageResourceType = typeof(ClassNameWithoutInput + Resources); // ArticleResources
ErrorMessageResourceName = typeof(PropertyName + "_Validation_Required"); // Body_Validation_Required

Is there any way to achieve something like this? maybe I need to implement a new ValidationAttribute.

+1  A: 

I don't think this is possible or, at least, not possible to do without also supplying a custom adapter for the attribute . You don't have any way in the constructor of the attribute to get access to the method/property that the attribute is applied to. Without that you can't get the type or property name information.

If you created an adapter for your attribute, then registered it with the DataAnnotationsModelValidatorProvider, then in the GetClientValidationRules, you would have access to the ControllerContext and model Metadata. From that you might be able to derive the correct resource type and name, then lookup the correct error message and add it to client validation rules for the attribute.

public class Required2AttributeAdapter
    : DataAnnotationsModelValidator<Required2Attribute>
{
    public Required2AttributeAdapter( ModelMetadata metadata,
                                      ControllerContext context,
                                      Required2Attribute attribute )
        : base( metadata, context, attribute )
    {
    }

    public override IEnumerable<ModelClientValidationRule>
        GetClientValidationRules()
    {
        // use this.ControllerContext and this.Metadata to find
        // the correct error message from the correct set of resources
        //
        return new[] {
            new ModelClientValidationRequiredRule( localizedErrorMessage )
        };
    }
}

Then in global.asax.cs

DataAnnotationsModelValidatorProvider.RegisterAdapter(
    typeof( Required2Attribute ),
    typeof( Required2AttributeAdapter )
);
tvanfosson
Can I use one adapter with any validation attribute? just use `DataAnnotationsModelValidator<ValidatoinAttribute>` ?
stacker
@stacker - The existing attributes already have adapters registered. The internal dictionary is keyed by the exact type as well so I think you need to have a single adapter per attribute type.
tvanfosson