Updating the response body in middleware .NET Core
Asked Answered
G

3

10

I have a custom middleware in my .NET Core 3.1 application, and trying to set the response StatusCode and Body like this:

public async Task Invoke(HttpContext context)
{
    if ( <some condition on context.Request> )
    {
        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        await context.Response.WriteAsync("my custom message");

        // Bad request, do not call next middleware.
        return;
    }

    // Call next middleware.
    await _requestDelegate(context);
}

With the above code, the StatusCode is correctly set, however, the response Body is empty. How can I write my custom message to the Body?

Update1:

Added await, but this won't solve the issue. Thanks @Jonesopolis for mentioning that.

Update 2

So I was testing the response in Swagger (I was also looking at the developer's Network tab). However, when I tested in Postman, I was getting the expected response body.

So the question really is why the response body wasn't showing up in Swagger/network tab?

Thanks!

Ganger answered 21/6, 2022 at 19:3 Comment(5)
try throwing an await on your WriteAsync lineProficiency
@Proficiency response body is still empty after adding await :(Ganger
I think you need a stream to copy your new contents to the response body. Simply using WriteAsync won't workPreach
https://mcmap.net/q/436041/-modify-middleware-responsePreach
UseStatusCodePagesCarlos
S
5

SwaggerUI was setting an accept: text/plain header with the request so ASP.NET Core was ignoring any content that wasn't set as this type.

Change your code:

public async Task Invoke(HttpContext context)
{
    if (xxxx)
    {
        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        context.Response.ContentType = "text/plain";   //add this line.....

        await context.Response.WriteAsync("my custom message");
        return;
    }
    await _requestDelegate(context);
        
}
Songstress answered 22/6, 2022 at 9:26 Comment(0)
L
3

Let me get it straight. I don't think Swagger is the issue here. How about specify exactly what the content type is, and more importantly, let response complete its work.

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
   //Unauthorized
   context.Response.Headers.Add("Content-Type", "application/json");
   context.Response.StatusCode = StatusCodes.Status401Unauthorized;
   await context.Response.WriteAsync(JsonConvert.SerializeObject(new
   {
       Msg = msg,
       LoginPath = _options.LoginPath.Value,
   }));
   await context.Response.CompleteAsync();
}
Leavelle answered 12/9, 2022 at 0:44 Comment(0)
U
0

It is not necessary to use return keyword in your first block. you can use else block to call next middleware. It works

  public class CustomMiddleware 
    {
        private readonly RequestDelegate requestDelegate;
        public CustomMiddleware(RequestDelegate requestDelegate)
        {
            this.requestDelegate = requestDelegate;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            if(httpContext.Request.Path.Value=="/Custom")
            {
                httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                await httpContext.Response.WriteAsync("my custom message");
                return;
            }
            else
            {
                await requestDelegate(httpContext);
            }
        }
    }
    public static class Middlewares
    {
        public static void UseMyCustomMiddleware(this IApplicationBuilder applicationBuilder)
        {
            applicationBuilder.UseMiddleware<CustomMiddleware>();
        }
    }
   
Uncivilized answered 21/6, 2022 at 20:16 Comment(4)
How's this different from what I originally had in the question?Ganger
that is the same only I have used extension methodUncivilized
and how this is going to solve the issue?Ganger
only use await and else block for another conditionUncivilized

© 2022 - 2024 — McMap. All rights reserved.