3

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.UseMiddlewarecomes after app.UseMvc, the middleware does not do anything (i.e., 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);
     }
 }
2
  • could you please share more code of your middleware because froom above code the missing part i found is requestdelegate more info here also have a look at this Commented Nov 5, 2019 at 9:42
  • 1
    @Miky thanks for the comment. the problem is gone by putting await _next(httpContext); outside the else Commented Nov 5, 2019 at 9:50

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. You mean it should NOT be inside else?
I added simple explanation of middleware to my answer, also for more information, check microsoft documentation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.