Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac property injection into System.ComponentModel.DataAnnotations ValidationAttribute

I am not able to perform property injection into a custom data annotation validation attribute

 public class CustomValidationAttribute : ValidationAttribute 
 {
    public ILogger Logger { get; set; }

    public CustomValidationAttribute(string keyPointer)
    { }

    public override bool IsValid(object value)
    {
        // Implementation here
        return true;
    }
}

Now, on my MVC Application_Start method I have the following Autofac configuration:

        // Autofac Ioc Container
        var builder = new ContainerBuilder();
        builder.RegisterType<Logger>().As<ILogger>().InstancePerHttpRequest();
        builder.RegisterType<CustomValidationAttribute>()
        .OnActivating(e =>
        {
            e.Instance.Logger = e.Context.Resolve<ILogger>();
        });
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

I have also tried the autowiring capabilities:

builder.RegisterType<CustomValidationAttribute>().PropertiesAutowired();

I am guessing that the properties of an attribute on data annotations are resolved at compile time and are immune to runtime injection. This methods works fine for MVC filter attributes but does not work for data annotation attributes.

Any help is really appreciated on alternate methods to make this work.

like image 770
Diego Avatar asked Sep 19 '26 10:09

Diego


2 Answers

For reference, we had a problem with a ValidationAttribute which needed to do some database work using a Repository, which in turn used an Entity Framework DbContext.

Our problem was that the DbContext was being cached by the attribute. This led to the data it contained being stale which affected the result of the validation!

We fixed it by doing our Repository resolve inside an Autofac Lifetimescope declaration inside the IsValid method:

using Autofac;

...

public override bool IsValid(object value)
{
    using (var lifetimeScope = MvcApplication.Container.BeginLifetimeScope())
    {
        var repo = lifetimeScope.Resolve<IMyRepo>();

        // Do your validation checks which require the repo here

    } // The repo will be released / disposed here
}

Just adding my solution here as I haven't found this solution documented for this problem anywhere else - perhaps it's just so obvious nobody else has been as dumb as me :)

like image 174
Dave R Avatar answered Sep 21 '26 01:09

Dave R


You are correct in your analysis - Autofac has a mechanism to inject into Filter Attributes [which is achieved by not instantiating them as attributes and leans on facilities exposed MVC 3].

There is no such natural extension point applicable to Validation Attributes, and Autofac doesn't make any attempt to do so.

like image 32
Damian Schenkelman Avatar answered Sep 21 '26 02:09

Damian Schenkelman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!