Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to pass a Service Filter parameters?

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?

like image 749
Max Jacob Avatar asked Oct 17 '17 22:10

Max Jacob


3 Answers

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.

like image 126
Anestis Kivranoglou Avatar answered Nov 03 '22 08:11

Anestis Kivranoglou


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.

like image 33
Max Jacob Avatar answered Nov 03 '22 07:11

Max Jacob


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")]
like image 31
Roman Marusyk Avatar answered Nov 03 '22 09:11

Roman Marusyk