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?
Autofac is an open-source dependency injection (DI) or inversion of control (IoC) container developed on Google Code. Autofac differs from many related technologies in that it sticks as close to bare-metal C# programming as possible.
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 {}
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With