简体   繁体   中英

Middleware breaks the web api calls

I have a middleware to log web api requests. Below is the Configuration method inside Startup.cs . If app.UseMiddleware comes before app.UseMvc none of the web api calls get invoked However, if app.UseMiddleware comes after app.UseMvc , the middleware does not do anything (ie, recording requests).

I provided the code below. Any ideas why app.UseMiddleware interfers with asp.UseMvc ?

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
{
    // global cors policy
    app.UseCors(x => x
        .AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader());


    app.UseHttpsRedirection();
    app.UseAuthentication();

    app.UseStaticFiles();
    app.UseSpaStaticFiles();

    app.UseMiddleware<ApiLoggingMiddleware>();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
}

Below is the middleware:

 public async Task Invoke(HttpContext httpContext, IApiLogService apiLogService)
 {
     try
     {
         _apiLogService = apiLogService;

         var request = httpContext.Request;
         if (request.Path.StartsWithSegments(new PathString("/api")))
         {
             var stopWatch = Stopwatch.StartNew();
             var requestTime = DateTime.UtcNow;
             var requestBodyContent = await ReadRequestBody(request);
             var originalBodyStream = httpContext.Response.Body;

             await SafeLog(requestTime,
                   stopWatch.ElapsedMilliseconds,
                   200,//response.StatusCode,
                   request.Method,
                   request.Path,
                   request.QueryString.ToString(),
                   requestBodyContent
                   );           
         }
         else
         {
             await _next(httpContext);
         }
     }
     catch (Exception ex)
     {
         await _next(httpContext);
     }
 }

You have to always call await _next(httpContext); in middleware otherwise request does not go down the pipeline:

public async Task Invoke(HttpContext httpContext, IApiLogService apiLogService)
 {
     try
     {
         _apiLogService = apiLogService;

         var request = httpContext.Request;
         if (request.Path.StartsWithSegments(new PathString("/api")))
         {
             var stopWatch = Stopwatch.StartNew();
             var requestTime = DateTime.UtcNow;
             var requestBodyContent = await ReadRequestBody(request);
             var originalBodyStream = httpContext.Response.Body;

             await SafeLog(requestTime,
                   stopWatch.ElapsedMilliseconds,
                   200,//response.StatusCode,
                   request.Method,
                   request.Path,
                   request.QueryString.ToString(),
                   requestBodyContent
                   );           
         };
     }
     catch (Exception ex)
     {

     }
     await _next(httpContext);
 }

Edit (simple explanation of middleware):
The whole middleware thing works in the following way - When request comes to your application, it goes through middleware pipeline, where each middleware has to invoke next middleware in order to finally get the request to your controller. When you invoke await _next(httpContext); you are basically calling Invoke method of the next middleware in the pipeline. If you do not call await _next(httpContext); you are stopping the request and it wont come to your controller. One thing to notice is that when await _next(httpContext); returns, the request has already been served by your controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM