Autofac attribute injection failing on attributes

10,822

Solution 1

Your property of type IDataAccessProvider has to be public for injection to work. You can still mark DebugLogAttribute, IDataAccessProvider and it's implementation as internal if you prefer.

[DebugLogAttribute]
public class HOmeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

internal class DebugLogAttribute : ActionFilterAttribute
{
    public IDataAccessProvider DataAccess { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debugger.Break();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debugger.Break();
    }
}

internal interface IDataAccessProvider {}

internal class DataAccessProvider:IDataAccessProvider {}

Solution 2

I've been having the same issue in asp dotnet core but the current solution (making it public) doesn't seem to work. What I find odd is that the comment below is regarding a web-api but I'm using a normal ASP.NET Core MVC (MVC6). So if anyone has the same problem, try out the solution below.

https://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons

Unlike the filter provider in MVC, the one in Web API does not allow you to specify that the filter instances should not be cached. This means that all filter attributes in Web API are effectively singleton instances that exist for the entire lifetime of the application.

public override async Task OnActionExecutionAsync(
            ActionExecutingContext context,
            ActionExecutionDelegate next)
        {
            MyService = context.HttpContext.
                               RequestServices.GetService(typeof(IMyService)) as IMyService;
        }
Share:
10,822

Related videos on Youtube

anaximander
Author by

anaximander

I'm a software developer based in Evesham, UK. I work mainly with the ASP.NET web stack, and in my spare time I tinker with Xamarin mobile apps and some IoT gadgets. I'm fluent in C#, I can get by in SQL and Java, and I can still remember my C++ although it's a bit rusty these days. I'm slowly improving my skills in JavaScript and Angular after spending a few years confined to backend development, and I'm gaining confidence with Docker and Kubernetes as I use them in more projects at work and on my own time. I blog infrequently about a variety of topics mostly relating to software engineering, and I contribute to the occasional open-source project while maintaining a few NuGet packages of my own.

Updated on June 04, 2022

Comments

  • anaximander
    anaximander almost 2 years

    I've found a few questions on this, but they tend to point to the exact documentation I'm following... but it's still not working.

    I'm building a fairly simple ASP.NET MVC 4 site, and the plan is to use ActionFilterAttribute-based logging. I have a DataAccessProvider class which opens transactions with the database and provides unit-of-work instances, and I'm trying to inject it into the filter attribute.

    The documentation says that it's enough to just call RegisterFilterProvider(), and ensure that the relevant types are registered. It specifically says that there is no need to register the attribute, but I've tried both with and without. My code currently looks something like this:

    var builder = new ContainerBuilder();
    builder.RegisterControllers(Assembly.GetExecutingAssembly());
    
    builder.Register(x => new EntityAccessProvider())
        .As<IDataAccessProvider>()
        .InstancePerHttpRequest();
    
    builder.RegisterType<DebugLogAttribute>().PropertiesAutowired();
    // ^ I've tried it with and without this line
    
    builder.RegisterFilterProvider();
    var container = builder.Build();
    
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    

    The example in the docs then just places a property on the filter, so I've done the same:

    public class DebugLogAttribute : ActionFilterAttribute
    {
        private IDataAccessProvider DataAccess { get; set; }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext) { ... }
        public override void OnActionExecuted(ActionExecutedContext filterContext) { ... }
    }
    

    The docs say that's all is required - not even a constructor to inject into; it's done by property injection. When I run this code, however, The DataAccess property is always null; Autofac seems to ignore it. I know the registration works properly because it's correctly injecting EntityAccessProvider into my controllers, but it's not working for attributes. What am I missing?

  • anaximander
    anaximander over 10 years
    Oops... totally missed that. Thanks!
  • Redplane
    Redplane almost 8 years
    Thank you for your solution :)