[英]How to autoformat API response in .NET core 5 Web API project?
I Have an API with formatted response look's like this following JSON:我有一个带有格式化响应的 API,如下所示 JSON:
{
"statusCode": 200,
"totalRecord": 2,
"message": "Succesfully get merchants",
"data": [
{
"id": 1,
"name": "Leo Shop",
"address": "Flower Street 9A",
"isComplete": false,
"createdAt": "2021-05-30T14:16:27.654233",
"updatedAt": "2021-05-30T14:16:28.515476"
},
{
"id": 3,
"name": "Test Shop",
"address": "Playing Street 12A",
"isComplete": false,
"createdAt": "2021-05-30T14:16:27.654233",
"updatedAt": "2021-05-30T14:16:28.515476"
}
]
}
And code behind those response look's like this following code:这些响应背后的代码如下所示:
[HttpGet]
public async Task<ActionResult<IEnumerable<Merchant>>> GetMerchants()
{
var data = await _context.Merchants.ToListAsync();
ApiResponse res = new ApiResponse{StatusCode = 200, Message = "Succesfully get merchants", TotalRecord = data.Count, Data = data}; // Focus on this line
return Ok(res);
}
My question, how to automatically convert default response As ApiResponse
model without repeating to write new ApiResponse()
model on every action return inside every controller?我的问题,如何自动将默认响应转换为
ApiResponse
model 而无需在每个 controller 内的每个操作返回时重复编写new ApiResponse()
model?
Hopefully anyone can help me.. Thanks in advance guys希望任何人都可以帮助我..提前谢谢你们
You can use Result Filter in MVC Filter pipeline您可以在 MVC 过滤器管道中使用结果过滤器
So change your controller looks like this所以改变你的 controller 看起来像这样
[HttpGet]
public Task<List<Merchant>> GetMerchants()
{
return _context.Merchants.ToListAsync();
}
Add new class, called ResultManipulator.cs添加新的 class,名为 ResultManipulator.cs
public class ResultManipulator : IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
// do nothing
}
public void OnResultExecuting(ResultExecutingContext context)
{
//run code immediately before and after the execution of action results. They run only when the action method has executed successfully. They are useful for logic that must surround view or formatter execution.
var result = context.Result as ObjectResult;
var resultObj = result.Value;
//change this ResultApi with your ApiResponse class
var resp = new ResultApi
{
Path = context.HttpContext.Request.Path.HasValue ? context.HttpContext.Request.Path.Value : "",
Method = context.HttpContext.Request.Method
};
if (resultObj is not null && resultObj is not Unit)
resp.Payload = resultObj;
//you can also change this from System.Text.Json to newtonsoft if you use newtonsoft
context.Result = new JsonResult(resp, new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Converters = { new JsonStringEnumConverter() }
});
}
}
And dont forget to add ResultManipulator class in Startup并且不要忘记在 Startup 中添加 ResultManipulator class
services.AddControllers(options =>
{
options.Filters.Add(new ResultManipulator());
})
I hope it solve your problem我希望它能解决你的问题
Try this as a middleware solution.试试这个作为中间件解决方案。 It will transform the response.
它将改变响应。
public class YourResponseMiddleware
{
private readonly RequestDelegate _next;
public YourResponseMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
var existingBody = context.Response.Body;
using (var newBody = new MemoryStream())
{
context.Response.Body = newBody;
await _next(context);
var newResponse = await FormatResponse(context.Response);
context.Response.Body = new MemoryStream();
newBody.Seek(0, SeekOrigin.Begin);
context.Response.Body = existingBody;
var newContent = new StreamReader(newBody).ReadToEnd();
// Send modified content to the response body.
//
await context.Response.WriteAsync(newResponse);
}
}
private async Task<string> FormatResponse(HttpResponse response)
{
//We need to read the response stream from the beginning...and copy it into a string...I'D LIKE TO SEE A BETTER WAY TO DO THIS
//
response.Body.Seek(0, SeekOrigin.Begin);
var content= await new StreamReader(response.Body).ReadToEndAsync();
var yourResponse = new YourResponse (); // CREATE THIS CLASS
yourResponse.StatusCode = response.StatusCode;
if(!IsResponseValid(response))
{
yourResponse.ErrorMessage = content;
}
else
{
yourResponse.Content = content;
}
yourResponse.Size = response.ToString().Length;
var json = JsonConvert.SerializeObject(yourResponse );
//We need to reset the reader for the response so that the client an read it
response.Body.Seek(0, SeekOrigin.Begin);
return $"{json}";
}
private bool IsResponseValid(HttpResponse response)
{
if ((response != null)
&& (response.StatusCode == 200
|| response.StatusCode == 201
|| response.StatusCode == 202))
{
return true;
}
return false;
}
}
public static class ResponseMiddleware
{
public static void UseYourResponseMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<YourResponseMiddleware>();
}
}
In Startup.cs (Configure())在 Startup.cs (Configure())
app.UseYourResponseMiddleware();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.