Asp.Net Core 2.x中间件语法

时间:2018-06-20 01:33:54

标签: c# asp.net-core .net-core middleware

我遇到了几种直接在Startup.Configure()方法中编写简单中间件的方法:

// Syntax 1.
app.Use((context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    return next();
});

// Syntax 2.
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    await next();
});

// Syntax 3.
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    await next.Invoke();
});

// Syntax 4.
app.Use(next =>
{
    return ctx =>
    {
        ctx.Response.Headers.Add("X-Content-Type-Options", "nosniff");
        return next(ctx);
    };
});

它们都一样吗?

2 个答案:

答案 0 :(得分:4)

语法4使用Use的{​​{1}}方法

IApplicationBuilder

语法1、2和3对IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware) 使用扩展方法,这是语法4中先前方法的包装。这就是隐含的意思

IApplicationBuilder

对于语法2和3,public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware) { return app.Use(next => { return context => { Func<Task> simpleNext = () => next(context); return middleware(context, simpleNext); }; }); } next.Invoke()之间没有区别。它们都编译为相同的方法。

答案 1 :(得分:2)

语法1和语法2在功能上有所不同。语法1不等待next()完成其Task。语法1将普通的lambda函数传递给Use,并且返回Task而不等待它完成。语法2正在传递async lambda函数,并且在返回之前是awaiting Taskawait关键字告诉应用程序暂停执行,直到next()任务完成为止。在您的示例代码中,这可能不会导致功能上的差异,但是有时等待Task完成可能会有所不同。

语法2和语法3在语法上不同且功能相同。语法2只是语法3的用户友好版本。请参见Func<T>() vs Func<T>.Invoke()

语法1和语法4在语法上不同且功能相同。语法1只是围绕语法4的用户友好包装器。请参见UseExtension.cs

// syntax 1,2,3 use this 
public static IApplicationBuilder Use(
    this IApplicationBuilder app, 
    Func<HttpContext, Func<Task>, Task> middleware)
{
    // which calls into syntax4
    return app.Use(next =>
    {
        return context =>
        {
            Func<Task> simpleNext = () => next(context);
            return middleware(context, simpleNext);
        };
    });
}