using System.Threading.Tasks;
using System.Text;
public class HttpContextSample
{
public StringBuilder Output { get; set; }
public HttpContextSample() {
Output = new StringBuilder();
}
}
public delegate Task RequestDelegate(HttpContextSample context);
这样,我们可以定义一个基础的,使用 RequestDelegate 的示例代码 。
// 定义一个表示处理请求的委托对象
RequestDelegate app = context =>
{
context.Output.AppendLine("End of output.");
return Task.CompletedTask;
};
// 创建模拟当前请求的对象
var context1 = new HttpContextSample();
// 处理请求
app(context1);
// 输出请求的处理结果
Console.WriteLine(context1.Output.ToString());
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Builder
{
public class ApplicationBuilder : IApplicationBuilder
{
private const string ServerFeaturesKey = "server.Features";
private const string ApplicationServicesKey = "application.Services";
private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();
public ApplicationBuilder(IServiceProvider serviceProvider)
{
Properties = new Dictionary<string, object?>(StringComparer.Ordinal);
ApplicationServices = serviceProvider;
}
public ApplicationBuilder(IServiceProvider serviceProvider, object server)
: this(serviceProvider)
{
SetProperty(ServerFeaturesKey, server);
}
private ApplicationBuilder(ApplicationBuilder builder)
{
Properties = new CopyOnWriteDictionary<string, object?>(builder.Properties, StringComparer.Ordinal);
}
public IServiceProvider ApplicationServices
{
get
{
return GetProperty<IServiceProvider>(ApplicationServicesKey)!;
}
set
{
SetProperty<IServiceProvider>(ApplicationServicesKey, value);
}
}
public IFeatureCollection ServerFeatures
{
get
{
return GetProperty<IFeatureCollection>(ServerFeaturesKey)!;
}
}
public IDictionary<string, object?> Properties { get; }
private T? GetProperty<T>(string key)
{
return Properties.TryGetValue(key, out var value) ? (T)value : default(T);
}
private void SetProperty<T>(string key, T value)
{
Properties[key] = value;
}
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
_components.Add(middleware);
return this;
}
public IApplicationBuilder New()
{
return new ApplicationBuilder(this);
}
public RequestDelegate Build()
{
RequestDelegate app = context =>
{
// If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened.
// This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware.
var endpoint = context.GetEndpoint();
var endpointRequestDelegate = endpoint?.RequestDelegate;
if (endpointRequestDelegate != null)
{
var message =
$"The request reached the end of the pipeline without executing the endpoint: '{endpoint!.DisplayName}'. " +
$"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " +
$"routing.";
throw new InvalidOperationException(message);
}
context.Response.StatusCode = StatusCodes.Status404NotFound;
return Task.CompletedTask;
};
foreach (var component in _components.Reverse())
{
app = component(app);
}
return app;
}
}
}
using System.Threading.Tasks;
public class RequestCultureMiddleware {
private readonly RequestDelegate _next;
public RequestCultureMiddleware (RequestDelegate next) {
_next = next;
}
public async Task InvokeAsync (HttpContextSample context) {
context.Output.AppendLine("Middleware 4 Processing.");
// Call the next delegate/middleware in the pipeline
await _next (context);
}
}
在演示程序中使用按照约定定义的中间件 。
Func<RequestDelegate, RequestDelegate> middleware4 = next => {
return (HttpContextSample context) => {
var step4 = new RequestCultureMiddleware(next);
// 中间件 4 的处理
var result = step4.InvokeAsync (context);
return result;
};
};
_components.Add (middleware4);
在 ASP.NET Core 中使用按照约定定义的中间件语法与使用强类型方式相同:
.UseMiddleware<RequestCultureMiddleware >();
中间件的顺序
中间件安装一定顺寻构造成为请求处理管道,常见的处理管道如下所示:
实现 BeginRequest 和 EndRequest
理解了请求处理管道的原理,下面看它的一个应用 。
在 ASP.NET 中我们可以使用预定义的 Begin_Request 和 EndRequest 处理步骤 。
public class BeginEndRequestMiddleware
{
private readonly RequestDelegate _next;
public BeginEndRequestMiddleware(RequestDelegate next)
{
_next = next;
}
public void Begin_Request(HttpContext context) {
// do begin request
}
public void End_Request(HttpContext context) {
// do end request
}
public async Task Invoke(HttpContext context)
{
// Do tasks before other middleware here, aka 'BeginRequest'
Begin_Request(context);
// Let the middleware pipeline run
await _next(context);
// Do tasks after middleware here, aka 'EndRequest'
End_Request();
}
}
Register
public void Configure(IApplicationBuilder app)
{
// 第一个注册
app.UseMiddleware<BeginEndRequestMiddleware>();
// Register other middelware here such as:
app.UseMvc();
}