Reputation: 8026
I encountered several ways of writing simple middleware directly in Startup.Configure() method:
// 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);
};
});
Are they all the same?
Upvotes: 11
Views: 1028
Reputation: 14995
Syntax 4 is using Use
method of IApplicationBuilder
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
Syntax 1, 2 and 3 are using an extension method for IApplicationBuilder
which is a wrapper of previous method in Syntax 4. Here's the implimentation
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);
};
});
}
For Syntax 2 and 3, there is no difference between next.Invoke()
and next()
. They both compile to the same method.
Upvotes: 6
Reputation: 141434
Syntax 1 and Syntax 2 are functionally different. Syntax 1 does not wait for next()
to finish its Task
. Syntax 1 is passing a normal lambda function to Use
and is returning the Task
without waiting for it to complete. Syntax 2 is passing an async
lambda function and is awaiting
the Task
before returning. The await
keyword tells the app to pause execution until the next()
task is complete. In the code from your example, that might not lead to a functional difference, but there are times when waiting for a Task
to complete can make a difference.
Syntax 2 and Syntax 3 are syntactically different and functionally identical. Syntax 2 is just a user-friendly versions of Syntax 3. See Func<T>() vs Func<T>.Invoke()
Syntax 1 and Syntax 4 are syntactically different and functionally identical. Syntax 1 is just a user-friendly wrapper around Syntax 4. See 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);
};
});
}
Upvotes: 7