我是asp.net-core的新手,我对app.run和app.useendpoints感到困惑,两者之间有什么区别?它们的劣势有一些优点吗?我尝试在3.0中使用app.run,但不确定是否有必要?有人可以建议吗?
答案 0 :(得分:1)
对于app.Run
,它将终端中间件委托添加到应用程序的请求管道中。
对于app.Use
,它将中间件委托添加到应用程序的请求管道中。
对于app.Run
和app.UseEndpoints
之间的差异,它是app.Run
和app.Use
之间的差异。 app.Run
将结束请求,而app.Use
会将请求传递给下一个中间件。
对于app.UseEndpoints
,它是app.Use
与EndpointMiddleware
。
一些关键代码,例如:
public static IApplicationBuilder UseEndpoints(this IApplicationBuilder builder, Action<IEndpointRouteBuilder> configure)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
VerifyRoutingServicesAreRegistered(builder);
VerifyEndpointRoutingMiddlewareIsRegistered(builder, out var endpointRouteBuilder);
configure(endpointRouteBuilder);
// Yes, this mutates an IOptions. We're registering data sources in a global collection which
// can be used for discovery of endpoints or URL generation.
//
// Each middleware gets its own collection of data sources, and all of those data sources also
// get added to a global collection.
var routeOptions = builder.ApplicationServices.GetRequiredService<IOptions<RouteOptions>>();
foreach (var dataSource in endpointRouteBuilder.DataSources)
{
routeOptions.Value.EndpointDataSources.Add(dataSource);
}
return builder.UseMiddleware<EndpointMiddleware>();
}
UseMidleware
类似于
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder app, Type middleware, params object[] args)
{
if (typeof(IMiddleware).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo()))
{
// IMiddleware doesn't support passing args directly since it's
// activated from the container
if (args.Length > 0)
{
throw new NotSupportedException(Resources.FormatException_UseMiddlewareExplicitArgumentsNotSupported(typeof(IMiddleware)));
}
return UseMiddlewareInterface(app, middleware);
}
var applicationServices = app.ApplicationServices;
return app.Use(next =>
{
var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public);
var invokeMethods = methods.Where(m =>
string.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal)
|| string.Equals(m.Name, InvokeAsyncMethodName, StringComparison.Ordinal)
).ToArray();
if (invokeMethods.Length > 1)
{
throw new InvalidOperationException(Resources.FormatException_UseMiddleMutlipleInvokes(InvokeMethodName, InvokeAsyncMethodName));
}
if (invokeMethods.Length == 0)
{
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNoInvokeMethod(InvokeMethodName, InvokeAsyncMethodName, middleware));
}
var methodInfo = invokeMethods[0];
if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType))
{
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNonTaskReturnType(InvokeMethodName, InvokeAsyncMethodName, nameof(Task)));
}
var parameters = methodInfo.GetParameters();
if (parameters.Length == 0 || parameters[0].ParameterType != typeof(HttpContext))
{
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNoParameters(InvokeMethodName, InvokeAsyncMethodName, nameof(HttpContext)));
}
var ctorArgs = new object[args.Length + 1];
ctorArgs[0] = next;
Array.Copy(args, 0, ctorArgs, 1, args.Length);
var instance = ActivatorUtilities.CreateInstance(app.ApplicationServices, middleware, ctorArgs);
if (parameters.Length == 1)
{
return (RequestDelegate)methodInfo.CreateDelegate(typeof(RequestDelegate), instance);
}
var factory = Compile<object>(methodInfo, parameters);
return context =>
{
var serviceProvider = context.RequestServices ?? applicationServices;
if (serviceProvider == null)
{
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareIServiceProviderNotAvailable(nameof(IServiceProvider)));
}
return factory(instance, context, serviceProvider);
};
});
}
答案 1 :(得分:0)
区别是基本的,爱德华在解释方面做得很好,但我相信更简单的解释会更好。 App.Use 用于向 OWIN 管道添加中间件,App.Run 也用于相同目的。不同之处在于,一旦添加了 App.Run 的中间件完成其执行,管道将终止并且响应将返回给调用者。这是唯一的区别。让我举个例子。
app.Use((context, nextMidWare) => { context.Response.Body.Write("Written by app.Use"); nextMidWare(context);});
app.Run((context) => context.Response.Body.Write("Written by app.Run"));
app.Use((context, nextMidWare) => context.Response.Body.Write("Also written by app.Use"));
为了更好地传达我的解释,我稍微简化了方法签名。鉴于这些是唯一注册的中间件,当您从浏览器请求网站时,结果将如下所示。
Written by app.Use
Written by app.Run
正如您所看到的,最后一条消息“Also write by app.Use”尚未写入响应。原因当然是我们在使用 App.Run 注册了另一个中间件之后注册了关联的中间件。如果我们使用 App.Use 代替,那么我们也会观察到最后一条消息。
最后,App.UseEndpoints
类似于对 App.Use 方法的预配置调用,它为您提供某些功能,我建议您阅读一些关于此问题的 Microsoft 文档。
我建议您阅读以下内容: