Big Daddy
Big Daddy

Reputation: 5224

.Net Core Filters in a Gateway API

I'd like to incorporate filters into a Gateway API project that I've created. There are no controllers in this project (I think this is important to note). It fronts a number microservices, serves as a reverse proxy, and performs cross-cutting concerns as well as orchestration. I need to apply various filters to requests in the pipeline - mostly to include header data. I've not been able to apply the filters - breakpoints don't get hit and no exceptions.

I have 3 questions:

STARTUP.CS

public void ConfigureServices(IServiceCollection services)
        {
            var logger = _loggerFactory.CreateLogger<Startup>();
            services.AddCors(options =>
            {
                options.AddPolicy("app-cors-policy",
                    builder =>
                    {
                        builder
                            .AllowAnyOrigin()
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .AllowCredentials()
                            .WithExposedHeaders("Content-Disposition") //headers to be exposed
                        ;
                    });
            });

            services.AddMvc(options =>
            {
                options.Filters.Add(new ContentDispositionFilter(?????));
            });
        }

   public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {           
        app.UseCors("app-cors-policy").UseMvc();

        app.Run(async (context) =>
        {
            _router.Request = context.Request;
            var httpResponseMessage = await _router.RouteRequest();

            if (httpResponseMessage.IsSuccessStatusCode)
            {
//
// *** HOW DO I PASS httpResponseMessage TO A FILTER *** ???
//

Upvotes: 0

Views: 202

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239260

Well, you can't do both simultaneously. It's not clear if that's actually your requirement, but if so, you're out of luck.

To pass things in a design time, you literally use the constructor like any other class:

options.Filters.Add(new ContentDispositionFilter("foo"));

Which would then correspond to a constructor on that class like:

public ContentDispositionFilter(string myParam)

To add runtime dependencies, you'd have to utilize dependency injection. Simply, you make the constructor have params for the various dependencies:

public ContentDispositionFilter(Dependency1 dep1, Dependency2, dep2)

Then, to register the global filter, you'll have to do it by type, not reference. The way you're doing it currently is by reference, where your new it up in line. Instead, you'll need to do:

options.Filters.Add(typeof(ContentDispositionFilter));

And then, of course, you'll need to ensure that your filter is actually registered in the service collection:

services.AddScoped<ContentDispositionFilter>();

EDIT

It's worth mentioning that the service registration itself kind of gives you an opportunity to do both. You can actually pass a factory lambda to that like so:

services.AddScoped(p =>
{
    var dep1 = p.GetRequiredService<Dependency1>();
    return new ContentDispositionFilter("foo", dep1);
}

So here, you have some static thing (the string) you're passing in and getting a runtime service. The p param there is an instance of IServiceProvider, so you can retrieve any service you like from that.

EDIT #2

So, I just noticed the comment at the end of your code block:

//
// *** HOW DO I PASS httpResponseMessage TO A FILTER *** ???
//

Simply, you cannot. Not here. I'm not sure what you're ultimately trying to achieve, but this isn't the way to do it. This now seems to be an XY problem. Try creating a new question directly related to what you actually want, instead of the solution you think will get you there.

Upvotes: 1

Related Questions