app.UseRouting()和app.UseEndPoints()有什么区别?

Iva*_*ael 5 asp.net asp.net-mvc asp.net-mvc-4 asp.net-core

当我试图了解它们时,似乎它们都用于将请求路由/映射到某个端点

Ali*_*yat 46

UserRouting:将请求与端点匹配。

UseEndpoints:执行匹配的端点。

它将路由匹配和解析功能与端点执行功能分离,直到现在,这些功能都与 MVC 中间件捆绑在一起。

这使得 ASP.NET Core 框架更加灵活,并允许其他中间件在UseRoutingUseEndpoints之间进行操作。这允许这些中间件利用来自端点路由的信息,例如,对UseAuthentication的调用必须在UseRouting之后 进行,以便路由信息可用于身份验证决策和UseEndpoints之前,以便用户在访问端点之前进行身份验证。


Ham*_*aei 29

基于 dotnet 核心文档:

????????????????????????????????????????????????????????????????????????????????????
?             app.UseRouting()             ?          app.UseEndPoints()           ?
????????????????????????????????????????????????????????????????????????????????????
?               Find Endpoint              ?           Execute Endpoint            ?
?                                          ?                                       ?
?  Adds route matching to the middleware   ?  Adds endpoint execution to the       ?
?  pipeline. This middleware looks at the  ?  middleware pipeline.                 ?
?  set of endpoints defined in the app,    ?  It runs the delegate associated      ?
?  and selects the best match based        ?  with the selected endpoint.          ?
?  on the request.                         ?                                       ?
?                                          ?                                       ?
????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

基于上表,我们应该注意一些提示:

  1. 如果应用程序调用UseStaticFiles,地方UseStaticFilesUseRouting

  2. AuthenticationAuthorization中间件放在 UseRouting 和 UseEndPoints 之间很重要

  3. UseRouting()调用之后出现的任何中间件都将知道最终将运行哪个端点。

  4. UseRouting()调用之前出现的任何中间件都不知道最终将运行哪个端点。


Rya*_*yan 17

首先,你可以看看他们的源代码

1.使用路由

public static IApplicationBuilder UseRouting(this IApplicationBuilder builder)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        VerifyRoutingServicesAreRegistered(builder);

        var endpointRouteBuilder = new DefaultEndpointRouteBuilder(builder);
        builder.Properties[EndpointRouteBuilder] = endpointRouteBuilder;

        return builder.UseMiddleware<EndpointRoutingMiddleware>(endpointRouteBuilder);
    }
Run Code Online (Sandbox Code Playgroud)

2.使用端点

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>();
    }
Run Code Online (Sandbox Code Playgroud)

然后参考方法“UseRouting”的无重载需要 1 个参数,详细解释了它们之间的差异。

ASP.NET Core 3 使用改进的端点路由,这通常会对应用程序内的路由提供更多控制。端点路由分为两个独立的步骤:

在第一步中,请求的路由与配置的路由再次匹配,以确定正在访问的路由。

在最后一步中,正在评估确定的路由并调用相应的中间件,例如 MVC。

这两个步骤由 app.UseRouting() 和 app.UseEndpoints() 设置。前者将注册运行逻辑以确定路由的中间件。然后后者将执行该路线。

另外,请参考

https://asp.net-hacker.rocks/2019/08/12/aspnetcore30-look-into-startup.html https://aregcode.com/blog/2019/dotnetcore-understanding-aspnet-endpoint-routing/

  • 这是多么糟糕的设计啊,我们必须深入框架的代码才能弄清楚它的含义。 (11认同)

小智 13

UseRouting() 添加的中间件计算应将哪个路由用于请求 URL 路径,但此时不在管道中进行路由。它添加了可供后续中间件使用的元数据。

UseEndpoints()添加的中间件执行Controller和相应的处理程序。

UseEndpoints() 也是您实际注册应用程序所有端点的地方

看看这篇有用的文章:https://andrewlock.net/converting-a-terminal-middleware-to-endpoint-routing-in-aspnetcore-3/


Ash*_*h K 6

这里已经有了很好的答案,但让我用一个更解释的例子来添加我的答案。这全部来自优秀的文档

定义:

  1. UseRouting将路由匹配添加到中间件管道。该中间件查看应用程序中定义的端点集,并根据请求选择最佳匹配。

    简而言之: URL 与端点匹配。

  2. UseEndpoints将端点执行添加到中间件管道。它运行与所选端点关联的委托。

    简而言之: 注册实际端点。

例子:

// Location 1: before routing runs, endpoint is always null here.
// This will run for any endpoint. "/" or "/abc" or "/def" or whatever.
// It won't have any endpoint because it's placed before app.UseRouting()
app.Use(async (context, next) =>
{
    Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    await next(context);
});

app.UseRouting();

// Location 2: after routing runs, endpoint will be non-null if routing found a match.
// This will run for any endpoint. "/" or "/abc" or "/def" or whatever.
// It will have an endpoint only for "/" because there's a match for "/" below (app.MapGet("/"...)
app.Use(async (context, next) =>
{
    Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    await next(context);
});

// Location 3: runs when this endpoint matches
// This will run only for "/"
// Will have an endpoint (Of course! Duh!)
app.MapGet("/", (HttpContext context) =>
{
    Console.WriteLine($"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    return "Hello World!";
}).WithDisplayName("Hello");

//UseEndpoints middleware is terminal when a match is found
//The middleware after UseEndpoints execute only when no match is found
app.UseEndpoints(_ => { });

// Location 4: runs after UseEndpoints - will only run if there was no match.
// This will run for any endpoint except "/". For eg: "/abc" or "/def" or whatever.
app.Use(async (context, next) =>
{
    Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    await next(context);
});
Run Code Online (Sandbox Code Playgroud)

使用显示的 URL 运行此代码"/"

1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello
Run Code Online (Sandbox Code Playgroud)

使用任何其他 URL 运行此代码会显示:

1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)
Run Code Online (Sandbox Code Playgroud)