Learning ASP. NET Core, how can I not understand the request processing pipeline [5]: In addition to using Startup for middleware registration, you can also choose StartupFilter,
In addition to the Startup object (DelegateStartup or ConventionBasedStartup), you can also use another object called StartupFilter. StartupFilter is a general term for all types and objects that implement the IStartupFilter interface. The IStartupFilter interface defines, for example, the next unique method Configure. The Action <IApplicationBuilder> object returned by the parameter next of this method reflects the subsequent registration of the middleware by StartupFilter and Startup, the registration of the middleware is implemented in the returned Action <IApplicationBuilder> object. [This Article has been synchronized to ASP. NET Core framework secrets]
1: public interface IStartupFilter
2: {
3: Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next);
4: }
We can use the service registration method to register multiple startupfilters. Specifically, StartupFilter has the following two different registration methods: one is to call the ConfigureServices method of WebHostBuilder to register the required StartupFilter in the form of a service, the other is to implement service registration for StartupFilter on the ConfigureServices method of the startup class.
1: // registration method 1
2: new WebHostBuilder()
3: .ConfigureServices(svcs => svcs
4: .AddSingleton<IStartupFilter, Filter1>()
5: .AddSingleton<IStartupFilter, Filter2>())
6: …
7:
8: // registration method 2
9: public class Startup
10: {
11: public void ConfigureServices(IServiceCollection svcs)
12: {
13: svcs.AddSingleton<IStartupFilter,Filter1>()
14: .AddSingleton<IStartupFilter, Filter2>();
15: }
16: }
Since the middleware can be registered through Startup and StartupFilter at the same time, what is the difference between the middleware registered through these two methods? In fact, the only difference between them is that the middleware registered by StartupFilter will be executed first. In other words, for a pipeline composed of registered middleware, the middleware registered through Startup is located after the middleware registered through StartupFilter. We may wish to prove this through a simple example. In an ASP. the following four middleware types (Foo, Bar, Baz, and Gux) are defined in the. NET Core console application. Their processing logic for requests is simple, that is, to write their own type names to the request response.
1: public abstract class MiddlewareBase
2: {
3: private RequestDelegate _next;
4:
5: public MiddlewareBase(RequestDelegate next)
6: {
7: _next = next;
8: }
9: public async Task Invoke(HttpContext context)
10: {
11: await context.Response.WriteAsync($"{this.GetType().Name}=>");
12: await _next(context);
13: }
14: }
15:
16: public class Foo : MiddlewareBase
17: {
18: public Foo(RequestDelegate next) : base(next){}
19: }
20: public class Bar : MiddlewareBase
21: {
22: public Bar(RequestDelegate next) : base(next) {}
23: }
24: public class Baz : MiddlewareBase
25: {
26: public Baz(RequestDelegate next) : base(next) {}
27: }
28: public class Gux : MiddlewareBase
29: {
30: public Gux(RequestDelegate next) : base(next) {}
31: }
Next, we define the next generic StartupFilter <TMiddleware> class. This is a StartupFilter specifically used to register a specified type of middleware. Generic parameters represent the registered middleware type. In the Configure method, we implement the registration of middleware in the returned Action <IApplicationBuilder> object.
1: public class StartupFilter<TMiddleware> : IStartupFilter
2: {
3: public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
4: {
5: return app=> {
6: app.UseMiddleware<TMiddleware>();
7: next(app);
8: };
9: }
10: }
We finally compiled the following simple program to start the hosted application. As shown in the following code snippet, before using WebHostBuilder to create and start WebHost, we call its ConfigureServices method to register two StartupFilter <TMiddleware> objects, the corresponding middleware types are Foo and Bar. In the Configure method subsequently called, we have completed registration for the intermediate Baz and Gux. This program actually registers five middleware (calling the Run method of ApplicationBuilder can be regarded as the middleware registration ).
1: public class Program
2: {
3: public static void Main()
4: {
5: new WebHostBuilder()
6: .UseKestrel()
7: .ConfigureServices(svcs => svcs
8: .AddSingleton<IStartupFilter>(new StartupFilter<Foo>())
9: .AddSingleton<IStartupFilter>(new StartupFilter<Bar>()))
10: .Configure(app => app
11: .UseMiddleware<Baz>()
12: .UseMiddleware<Gux>()
13: .Run(async context=> await context.Response.WriteAsync("End")))
14: .Build()
15: .Run();
16: }
17: }
Now we need to determine the execution sequence of the five registered requests during request processing. For this reason, we directly start this program and then open the browser to access the default listening address (http: // localhost: 5000 ), the browser displays the "Route" of the request in the five middleware as shown in ". The result displayed by the browser clearly indicates that the middleware registered through StartupFilter is executed first than the middleware registered through Startup. For two middleware registered in the same way, the first registered middleware will be executed first.