0

I needed a custom file provider, and to access a request's HttpContext, I found a solution using IHttpContextAccessor:

app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/res", StringComparison.OrdinalIgnoreCase), appBuilder =>
{    
    appBuilder.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new HostResFileProvider(appBuilder.ApplicationServices.GetRequiredService<IHttpContextAccessor>(), builder.Environment),
        RequestPath = "/res"
    });
});

While that worked just fine, looking at that code snippet I just started to wonder, instead of setting up IHttpContextAccessor wouldn't it be possible to pass the ctx variable instead, something like this?

app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/res", StringComparison.OrdinalIgnoreCase), appBuilder =>
{    
    appBuilder.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new HostResFileProvider(ctx, builder.Environment),
        RequestPath = "/res"
    });
});

Now, this won't work, though is there a way making it work?

1 Answer 1

1

HttpContext is scoped to HTTP request, that is why you must always use IHttpCOntextAccessor in services, in order to reliably access HttpContext related to current HTTP request being handled.

What you wanted to do is just passing single fixed context reference, that would be used for all static files requests. Which is simply not valid (and why, please read below explanations).

UPDATE

If you would put a breakpoint at your condition and inside the second lambda with appBuilder, you would see that this lambda is called once on the application build. At this time there's not even a HttpContext you could use. This is registered as part of a pipeline.

So, when the pipeline is built, it only checks the condition on each HTTP request and conditionally invokes this part of pipeline.

However the pipeline won't be rebuilt every HTTP request.

UPDATE 2

If you would look at the source code of UseWhen, last argument is Action<IApplicationBuilder> configuration and is used in one place (the other one is just null check):

var branchBuilder = app.New();
configuration(branchBuilder);

which then is used in middleware definition with app.Use.

So, the delegate is used at application startup. Not during HTTP request. Without HTTP request it is impossible to get HTTP context, thus your definition would be invalid if you'd try to bind HTTP context on app startup (even if you would figure out how).

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for answering. Given the second snippet doesn't work at all, what do you mean with "not valid"?
Also given the variable ctx actually is the HttpContext, and is set up to execute on each request using UseWhen to determine if the first segment is "/res", my question is about that, and why that can't be used. So given that, I'm not satisfied with an answer saying "simply not valid" and hope you explain that part a little bit more.
@Asons I have made some digging and added few details.
The UseWhen itself binds the HttpContext at the start-up level, or else i won't be able to evaluate ctx.Request.Path.StartsWithSegments("/res") on a request, and given it does, I was thinking it should/could be possible to pass it forward to the StaticFileOptions, but I guess the last part is set up and then can't make use of the request i the same way UseWhen does.
I stand corrected, it of course set up a delegate that deal with the incoming request, so make sence why one need IHttpContextAccessor being set up in a similar way.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.