ASP.NET Core 2.1 Middleware возвращает 404 - PullRequest
0 голосов
/ 03 октября 2018

Я решил создать собственное промежуточное программное обеспечение для ASP.NET API core 2.1.

public class AuthorizeMiddleware
{
    private readonly RequestDelegate _next;
    private readonly AuthorizeOptions _options;

    public AuthorizeMiddleware(RequestDelegate next, AuthorizeOptions options)
    {
        _next = next;
        _options = options;
    }


    public async Task Invoke(HttpContext context)
    {
        bool hasRole = false;
        if (hasRole)
        {
            await context.Response.WriteAsync($"Not authorized, you need role: {_options.Role}");
        }
        else
        {
            await _next.Invoke(context);
        }

    }

}        
public struct AuthorizeOptions
{
    public AuthorizeOptions(string role)
    {
        Role = role;
    }
    public string Role { get; set; }
} 

Когда я пытаюсь использовать это промежуточное ПО в моем Application.cs

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
            app.UseHttpsRedirection();
        }

        app.UseRouter(AuthenticatedRoutes(app));

        app.UseMvc();
    }

    private IRouter AuthenticatedRoutes(IApplicationBuilder applicationBuilder)
    {

        IRouteBuilder builder = new RouteBuilder(applicationBuilder);

        builder.MapMiddlewareGet("/api/values", appBuilder =>
        {
            appBuilder.UseMiddleware<AuthorizeMiddleware>(new AuthorizeOptions("User"));
            appBuilder.UseMvc();
        });

        return builder.Build();
    }

Это работаетпросто отлично, но когда я удаляю appBuilder.UseMvc ();из MapMiddlewareGet и по конкретному маршруту мой вызов функции возвращает 404.

Я попытался поставить appRouter выше app.useMvc ().Но безуспешно моя следующая функция промежуточного программного обеспечения все еще возвращала 404 при вызове _next.Invoke ().

Так почему useMvc () работает всякий раз, когда я вызываю его в appBuilder, я делаю что-то, что считается плохой практикой, и почему мне нужно app.useMvc () в MapMiddlewareGet ()?

1 Ответ

0 голосов
/ 04 октября 2018

То, что пытается сделать ваш AuthenticatedRoutes(), - это построить маршрутизатор с промежуточным программным обеспечением, таким образом, мы можем использовать окончательно возвращенный IRouter как RouterMiddleware для обработки запроса. Однако RouterMiddleware никогда не продолжит маршрутизацию, если уже есть обработчик, соответствующий .В результате он не будет «отправлять» запросы от одного RouterMiddlware к другому RouterMiddleware автоматически.

Давайте рассмотрим ваш код:

app.UseRouter(AuthenticatedRoutes(app));

Как вы знаете, метод app.UseRouter() здесь представляет собой метод расширения, который просто использует RouterMiddlware.Итак, первый вопрос: как работает промежуточное ПО маршрутизатора?Давайте рассмотрим исходный код:

public class RouterMiddleware
{
    private readonly IRouter _router;

    // ...

    public async Task Invoke(HttpContext httpContext)
    {
        var context = new RouteContext(httpContext);
        context.RouteData.Routers.Add(_router);
        await _router.RouteAsync(context);
        if (context.Handler == null){
            _logger.RequestDidNotMatchRoutes();
            await _next.Invoke(httpContext);
        } else {
            httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature(){
                RouteData = context.RouteData,
            };
            await context.Handler(context.HttpContext);
        }
    }
}

Как вы можете видеть здесь, RouterMiddleware маршрутизирует контекст и проверяет, есть ли RouterHandler соответствие:

  1. Еслиничего нет, ничего не делает, а затем отправляет запрос следующему промежуточному программному обеспечению .
  2. В противном случае обработайте запрос с помощью RouterHandler. Обратите внимание, что он никогда не отправит запрос следующему промежуточному программному обеспечению .

Давайте рассмотрим, как работает ваш маршрутизатор и RouterHandler:

private IRouter AuthenticatedRoutes(IApplicationBuilder applicationBuilder)
{

    IRouteBuilder builder = new RouteBuilder(applicationBuilder);

    builder.MapMiddlewareGet("/api/values", appBuilder =>
    {
        appBuilder.UseMiddleware<AuthorizeMiddleware>(new AuthorizeOptions("User"));
        appBuilder.UseMvc();
    });

    return builder.Build();
}

Видите это?Ваш маршрут проверит, является ли метод HTTP HttpGet и может ли URL соответствовать /api/values:

  1. Если это так, это означает, что маршрут соответствует, и определенный RouterHandler будет вызван для обработки запроса.

    • Сначала RouterHandler будет вызывать промежуточное программное обеспечение AuthorizeMiddleware
    • , если вы добавите appBuilder.UseMvc();, затем оно будет вызывать действие, соответствующее
    • , еслиappBuilder.UseMvc(); нет, он прекратит дальнейшую обработку и, в конечном итоге, даст ответ 404.
  2. Если нет, это означает, что маршрутизатор здесь не соответствует, иничего не сделает, а затем отправит запрос следующему промежуточному программному обеспечению.

...