I know that with regular Filters you can pass parameters like so:
[Filter(param="value")]
public ActionResult Action()
{
return View();
}
public class Filter : ActionFilterAttribute
{
public string param { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// do something with your parameter...
}
}
I have a Service Filter:
// MyCustomFilter.cs
namespace MyNamespace.Filters
{
public class MyCustomFilter : ActionFilterAttribute
{
public string param { get; set; }
// The services I'm injecting.
private ILogger _logger;
private IM3ObjectRepository _repo;
public MyCustomFilter(ILogger<MyCustomFilter> logger, IM3ObjectRepository repo)
{
_logger = logger;
_repo = repo;
}
public override void OnActionExecuting(ActionExecutingContext ctx)
{
_logger.LogInformation("Filter is working.");
// Get stuff from object repository, based on passed-in parameter.
}
}
}
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IM3ObjectRepository, M3ObjectRepository>();
services.AddScoped<M3UISecurityFilter>();
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
loggerFactory.AddSerilog();
...
}
// Example of filter being used.
[ServiceFilter(typeof(MyCustomFilter))]
public IActionResult Action(...)
{
...
}
The filter has some services injected into it. But each time I use the service I will also be sending in a parameter.
How would I achieve passing in a parameter? I can't find anything online describing how to do it similarly to a regular Filter. Is it even possible for a Service Filter?
TypeFilterAttribute Is defined exactly for this.
It is exactly like ServiceFilterAttribute except that it lets you pass constructor parameters that are not necessarily resolved from the IoC Container.
Example:
[TypeFilter(typeof(LogFilter), Arguments = new object[] {"myLogger"})]
[HttpGet("")]
public IEnumerable<Item> Get()
{
return this.repository.GetAll();
}
This article describes this neatly.
I have found an alternative:
// MyCustomFilter.cs
public class MyCustomFilter : ActionFilterAttribute
{
public string param { get; set; }
public override void OnActionExecuting(ActionExecutingContext ctx)
{
ILogger<MyCustomFilter> logger = (ILogger <MyCustomFilter>)ctx.HttpContext.RequestServices.GetService(typeof(ILogger<MyCustomFilter>));
IM3ObjectRepository repo = (IM3ObjectRepository)ctx.HttpContext.RequestServices.GetService(typeof(IM3ObjectRepository));
logger.LogInformation("Filter is working.");
// Get stuff from object repository, based on passed-in parameter.
}
}
// Example of filter being used.
[MyCustomFilter(param = "value you want")]
public IActionResult Action(...)
{
...
}
Instead of injecting the services I need, I am asking for them instead.
I'm now able to set and access the parameter I need.
I'm not marking this as the answer, because it doesn't answer the original question. But it does provide an alternative solution.
NOTE: The service for the custom Filter being added in Startup.cs is of course no longer required. The services that are used (e.g. in this case the object repository and the logger) are of course still required there.
Just try to extend it
public class CustomServiceFilterAttribute : ServiceFilterAttribute
{
public string Param { get; set; }
public CustomServiceFilterAttribute(Type type)
: base(type)
{
}
}
and use
[CustomServiceFilterAttribute(typeof(BaseHttpService), Param = "value")]
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