Is there a way to programmatically invoke the ASP.NET Core request pipeline from within my own application, given I have a HTTP verb, the route, headers and body payload?
There are use-cases where the WebAPI of our ASP.NET Core application is not accessible because the application is running behind a firewall or is otherwise not reachable.
To provide a solution for this scenario we want our application to poll some other service for "work-items" which then translate into API calls in our application.
Microsoft.AspNetCore.TestHost
package I could create a TestClient
which allows me to make requests to myself (see here). But there are a couple of uncertainties here:
TestHost
is for integration testing. Is it safe to use this in a production environment?TestServer
running alongside the regular hosting?TestClients
from a single TestServer
instance and use them from different threads?So I'm sure there must be a cleaner and more direct way to programmatically invoke the request pipeline from within my own application...
The ASP.NET Core request processing pipeline consists of a sequence of middleware components that are going to be called one after the other. Each middleware component can perform some operations before and after invoking the next component using the next method.
UseRouting , the Routing middleware runs at the beginning of the pipeline by default. For more information, see Routing. The order that middleware components are added in the Program. cs file defines the order in which the middleware components are invoked on requests and the reverse order for the response.
The pipeline is the general-purpose framework for server-side HTTP programming that serves as the foundation for ASP.NET pages as well as Web Services. To qualify as a serious ASP.NET developer, you must understand how the pipeline works. This article explains how the HTTP pipeline processes requests.
Configuring the Request Pipeline This is done in the Configure method of the startup class. The Configure method gets the instance of IApplicationBuilder, using which we can register our Middleware. Or You can create a new ASP.NET Core Application.
Yes, it is actually fairly easy. You can get a reference to the request pipeline at the end of your Startup class Configure method. Save it in a static field / singleton service / etc.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... usual configuration code
AClass.PipelineStaticField = app.Build();
}
Then, in the method you wish to inject the request, you have to build a HttpContext to pass into the pipeline.
var ctx = new DefaultHttpContext();
// setup a DI scope for scoped services in your controllers etc.
using var scope = _provider.CreateScope();
ctx.RequestServices = scope.ServiceProvider;
// prepare the request as needed
ctx.Request.Body = new MemoryStream(...);
ctx.Request.ContentType = "application/json";
ctx.Request.ContentLength = 1234;
ctx.Request.Method = "POST";
ctx.Request.Path = PathString.FromUriComponent("/mycontroller/action");
// you only need this if you are hosting in IIS (.UseIISIntegration())
ctx.Request.Headers["MS-ASPNETCORE-TOKEN"] = Environment.GetEnvironmentVariable("ASPNETCORE_TOKEN");
// setup a place to hold the response body
ctx.Response.Body = new MemoryStream();
// execute the request
await AClass.PipelineStaticField(ctx);
// interpret the result as needed, e.g. parse the body
ctx.Response.Body.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(ctx.Response.Body);
string body = await reader.ReadToEndAsync();
That way your request will traverse the whole pipeline including all the middleware such as authentication and authorization.
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