Wrapping All Answers

I want to wrap all my http responses.
For example, we have an action that returns some JSON data:

public IActionResult Get() 
{
    var res = new
        {
            MessageBody = "Test",
            SomeData = 1
        };

        return Ok(res);
}

I want my answer to look like this:

{    
    "StatusCode":200,
    "Result":
    {
        "MessageBody ":"Test",
        "SomeData":1        
    }
}

If there is an error, then the response should contain a field ErrorMessagein the response.

In mvc 5 I used DelegationHandler, but in the asp.net core this class is not implemented. Now we have to use middlewares.

This is the code for mvc 5:

public class WrappingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        return BuildApiResponse(request, response);
    }

    private static HttpResponseMessage BuildApiResponse(HttpRequestMessage request, HttpResponseMessage response)
    {
        object content;
        string errorMessage = null;

        if (response.TryGetContentValue(out content) && !response.IsSuccessStatusCode)
        {
            HttpError error = content as HttpError;

            if (error != null)
            {
                content = null;
                errorMessage = error.Message;

#if DEBUG
                errorMessage = string.Concat(errorMessage, error.ExceptionMessage, error.StackTrace);
#endif
            }
        }

        var newResponse = request.CreateResponse(response.StatusCode, new ApiResponse(response.StatusCode, content, errorMessage));

        foreach (var header in response.Headers)
        {
            newResponse.Headers.Add(header.Key, header.Value);
        }

        return newResponse;
    }
}

and, middleware for the asp.net core. In asp.net nucleus there TryGetContentValue, HttpErrorand other things. So, I first try to read the response body:

 public class FormatApiResponseMiddleware
 {
        private readonly RequestDelegate _next;

        public FormatApiResponseMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        private bool IsSuccessStatusCode(int statusCode)
        {
            return (statusCode >= 200) && (statusCode <= 299);

        }

        public async Task Invoke(HttpContext context)
        {
            object content = null;
            string errorMessage = null;

            if (!IsSuccessStatusCode(context.Response.StatusCode))
            {
                content = null;
                //how to get error 
            }

            var body= context.Response.Body;
        }
}

But the stream Bodyhas an CanReadequal false, and I get an error that the stream cannot be read. How to wrap the answer?

+4
1

ExceptionHandlerMiddleware / , .

, ,

// We can't do anything if the response has already started, just abort.
if (context.Response.HasStarted)
{
    _logger.LogWarning("The response has already started, the error handler will not be executed.");
    throw;
}

, :

context.Response.Clear();

, , . , JSON. , :

public class ErrorDto
{
   public int Code { get; set; }
   public string Message { get; set; }

   // other fields

   public override string ToString()
   {
      return JsonConvert.SerializeObject(this);
   }
}

Configure. , MVC, :

app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        context.Response.StatusCode = 500; // or another Status
        context.Response.ContentType = "application/json";

        var error = context.Features.Get<IExceptionHandlerFeature>();
        if (error != null)
        {
            var ex = error.Error;

            await context.Response.WriteAsync(new ErrorDto()
            {
                Code = 1, //<your custom code based on Exception Type>,
                Message = ex.Message // or your custom message
                // … other custom data
            }.ToString(), Encoding.UTF8);
        }
    });
});
0

Source: https://habr.com/ru/post/1657851/


All Articles