Actionfilter Injection in ASP.NET MVC 5
Although your question is different, the answer is exactly the same as this one.
DI friendly attributes should never define any behavior. You need to separate the behavior out into a separate filter that can have its dependencies injected at application startup. This can be done by splitting your action filter attribute into 2 parts.
- An attribute that contains no behavior to flag your controllers and action methods with.
- A DI-friendly class that implements IActionFilter and/or IAuthenticationFilter that contains the desired behavior with a scanning implementation to check for the attribute.
Don't let Microsoft's marketing of ActionFilterAttribute fool you. That approach is completely hostile to DI.
Aflred
Updated on June 04, 2022Comments
-
Aflred about 2 years
I have a simple filter.
public class IsAdmin : ActionFilterAttribute, IAuthenticationFilter { private string _roleName; IBusinessIdentity _identity; public IsAdmin(string roleName, IBusinessIdentity identity) { this._roleName = roleName; this._identity = identity; } public void OnAuthentication(AuthenticationContext filterContext) { } public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { if (!_identity.Roles.Contains(_roleName)) filterContext.Result = new HttpUnauthorizedResult(); } }
I am using Ninject. Here is my controller. I'm trying to get the injected service into my ActionFilter in order not to take a dependency on
HttpContext
but instead on myIBusinessIdentity
.IBusinessIdentity
gets injected the HttpContext.User.Identity`. And it does a few database calls and gets the userRoles.public class HomeController : Controller { readonly IBusinessIdentity _identity; public HomeController(IBusinessIdentity identity) { this._identity= identity; } [IsAdmin("Admin", _identity)] public ActionResult Index() { return View(); } }
This does not work and I'm getting a compiler error when I try to put the "identity" in the actionfilter constructor at compile time.
An object reference is required for the non-static field, method, or property
I need this because I'm planning to test various permissions with the identity.
I am thinking some kind of reflection to be done after controllers gets instantiated. I have a very vague idea on how it could be done.
I am using ASP.NET MVC 5 and I don't have the kernel.bindfilter. I can't use older version.
I am well aware of this hack.
Action filter constructor being called repeatedly for single controller
https://github.com/ninject/Ninject.Web.Mvc/wiki/Conditional-bindings-for-filters
How can I accomplish the same maybe effect using Ninject for MVC 5.
EDIT: massive failure
I forgot to include the:
using Ninject.Web.Mvc.FilterBindingSyntax;
Now everything works as explained in the above links.
Now I need to figure out how to inject the "roleName" string in the filter constructor. Although I think just construct a filter for every role. I will post entire code later.