У меня есть служба отдыха, написанная на Asp.Net Core, которая выполняет только операции CRUD. Интерфейс (угловые и собственные мобильные приложения) требует ответа конечной точки в следующем формате:
{
"isSuccessful": ложь,
"сообщение": ноль,
"датум": ноль
}
В API много контроллеров, и, поскольку я не хотел менять логику возврата всех методов всех контроллеров в API, я написал промежуточное ПО:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;
namespace HttpInterceptor.Classes
{
public class ResponseDatum
{
public bool IsSuccessful { get; set; }
public string Message { get; set; }
public object Datum { get; set; }
}
public class HttpMiddleware
{
private readonly RequestDelegate _next;
public HttpMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, DbContext dbContext)
{
if (context.Response.StatusCode.Equals(200))
{
Stream originalBody = null;
using MemoryStream modifiedBody = new MemoryStream();
using StreamReader streamReader = new StreamReader(modifiedBody);
context.Response.OnStarting((state) =>
{
context.Response.ContentType = "application/json";
return Task.CompletedTask;
}, null);
originalBody = context.Response.Body;
context.Response.Body = modifiedBody;
await _next.Invoke(context);
modifiedBody.Seek(0, SeekOrigin.Begin);
string originalContent = streamReader.ReadToEnd();
context.Response.Body = originalBody;
await context.Response.WriteAsync(JsonConvert.SerializeObject(new ResponseDatum
{
Datum = JsonConvert.DeserializeObject(originalContent),
IsSuccessful = true
}));
}
else
{
await _next.Invoke(context);
return;
}
}
}
public static class HttpMiddlewareExtensions
{
public static IApplicationBuilder UseHttpMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpMiddleware>();
}
}
}
Я хочу спросить, есть ли у этого подхода некоторые проблемы с производительностью, поскольку я перехватываю каждый запрос. И есть ли лучший способ добиться этого? Как какое-то глобальное отображение или атрибут фильтра?