Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 393 Vote(s) - 3.55 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can I use Dependency Injection in a .Net Core ActionFilterAttribute?

#1
**AuthenticationRequiredAttribute Class**


public class AuthenticationRequiredAttribute : ActionFilterAttribute
{
ILoginTokenKeyApi _loginTokenKeyApi;
IMemoryCache _memoryCache;

public AuthenticationRequiredAttribute(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;

_loginTokenKeyApi = new LoginTokenKeyController(new UnitOfWork());
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var memory = _memoryCache.Get(Constants.KEYNAME_FOR_AUTHENTICATED_PAGES);

string requestedPath = filterContext.HttpContext.Request.Path;

string tokenKey = filterContext.HttpContext.Session.GetString("TokenKey")?.ToString();

bool? isLoggedIn = _loginTokenKeyApi.IsLoggedInByTokenKey(tokenKey).Data;

if (isLoggedIn == null ||
!((bool)isLoggedIn) ||
!Constants.AUTHENTICATED_PAGES_FOR_NORMAL_USERS.Contains(requestedPath))
{
filterContext.Result = new JsonResult(new { HttpStatusCode.Unauthorized });
}
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
}
}

**HomeController**

public class HomeController : Controller
{
IUserApi _userApi;
ILoginTokenKeyApi _loginTokenKey;
IMemoryCache _memoryCache;

public HomeController(IUserApi userApi, ILoginTokenKeyApi loginTokenKey, IMemoryCache memoryCache)
{
_loginTokenKey = loginTokenKey;
_userApi = userApi;

_memoryCache = memoryCache;
}

[AuthenticationRequired] // There is AN ERROR !!
public IActionResult Example()
{
return View();
}
}

ERROR :

> Error CS7036 There is no argument given that corresponds to the
> required formal parameter 'memoryCache' of
> 'AuthenticationRequiredAttribute.AuthenticationRequiredAttribute(IMemoryCache)' Project.Ground.WebUI

**My problem is actually : I cant use dependency injection in attribute classes**.

I want to use that attribute without any parameter. Is there any solution to solve it? I use dependency injection but it cant be used for attributes. How I can use it?
Reply

#2
Instead of resolving at construction, `ActionExecutingContext.HttpContext.RequestServices` should give you a reference to the request's service container at the time of the request.

So:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var svc = filterContext.HttpContext.RequestServices;
var memCache = svc.GetService<IMemoryCache>();
//..etc
Reply

#3
As per [the documentation](

[To see links please register here]

), you have a few options here:

> If your filters have dependencies that you need to access from DI, there are several supported approaches. You can apply your filter to a class or action method using one of the following:
>
> * [`ServiceFilterAttribute`](

[To see links please register here]

)
> * [`TypeFilterAttribute`](

[To see links please register here]

)
> * [`IFilterFactory`](

[To see links please register here]

) implemented on your attribute

### ServiceFilter or TypeFilter attributes

If you just want to get this working quickly, you can just use one of the first two options to apply your filter to a controller or a controller action. When doing this, your filter does not need to be an attribute itself:

[TypeFilter(typeof(ExampleActionFilter))]
public IActionResult Example()
=> View();

The `ExampleActionFilter` can then just implement e.g. [`IAsyncActionFilter`](

[To see links please register here]

) and you can directly depend on things using constructor injection:

public class ExampleActionFilter : IAsyncActionFilter
{
private readonly IMemoryCache _memoryCache;
public ExampleActionFilter(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}

public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{ … }
}

You can also use the `[ServiceFilter]` attribute instead to get the same effect but then you will also need to register your `ExampleActionFilter` with the dependency injection container in your `Startup`.

### Filter factory

If you need more flexibility, you can implement your own filter factory. This allows you to write the factory code to create the actual filter instance yourself. A possible implementation for the above `ExampleActionFilter` could look like this:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ExampleActionFilterAttribute : Attribute, IFilterFactory
{
public bool IsReusable => false;

public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return serviceProvider.GetService<ExampleActionFilter>();
}
}

You can then use that `[ExampleActionFilter]` attribute to make the MVC framework create an instance of the `ExampleActionFilter` for you, using the DI container.

Note that this implementation is basically the same thing that `ServiceFilterAttribute` does. It’s just that implementing it yourself avoids having to use the `ServiceFilterAttribute` directly and allows you to have your own attribute.

### Using service locator

Finally, there is another quick option that allows you to avoid constructor injection completely. This uses the service locator pattern to resolve services dynamically when your filter actually runs. So instead of injecting the dependency and using it directly, you retrieve it explicitly from the context:

public class ExampleActionFilter : ActionFilterAttribute
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var memoryCache = context.HttpContext.RequestServices.GetService<IMemoryCache>();

// …
}
}
Reply

#4
For .Net Core 5, Below syntax worked for me.

IAppUserService _appUserService = (IAppUserService)context.HttpContext.RequestServices.GetService(typeof(IAppUserService));
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through