问题描述
我需要返回一个一致的响应,所有请求都返回一个类似的结构.在之前的 .NET web api 中,我可以使用 DelegatingHandler (MessageHandlers) 来实现这一点.我要返回的对象将被封装在 Result 元素中.所以基本上json响应会是这样的结构:
I need to return a consistent response with a similar structure returned for all requests. In the previous .NET web api, I was able to achieve this using DelegatingHandler (MessageHandlers). The object that I want to return will be encapsulated in the Result element. So basically the json response will be in this kind of structure:
示例 1:
{
"RequestId":"some-guid-abcd-1234",
"StatusCode":200,
"Result":
{
"Id":42,
"Todo":"Do Hello World"
}
}
示例 2:
{
"RequestId":"some-guid-abcd-1235",
"StatusCode":200,
"Result":
{
[
{
"Id":42,
"Todo":"Print Hello World"
},
{
"Id":43,
"Todo":"Print Thank you"
}
]
}
}
在 .NET 核心中,看起来我需要通过中间件来执行此操作.我试过了,但是当您可以调用 HttpResponseMessage.TryGetContentValue
来获取内容并将其包装在全局/通用响应模型中时,我没有看到更好的方法来提取内容,就像在以前的 Web API 中那样.
In .NET core, it looks like I need to do this via middleware. I tried but I don't see a nicer way to extract the content like how in the previous web API when you can call HttpResponseMessage.TryGetContentValue
to get the content and wrap it in global/common response model.
如何在 .NET core 中实现同样的功能?
How can I achieve the same in .NET core?
推荐答案
我创建了一个中间件来包装响应以保持一致性.为了方便注册这个中间件,我还为 IApplicationBuilder 创建了一个扩展方法.所以在 Startup.cs 中,注册中间件:
I created a middleware to wrap the response for consistency. I also created an extension method to IApplicationBuilder for convenience when registering this middleware. So in Startup.cs, register middleware :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//code removed for brevity.
...
app.UseResponseWrapper();
//code removed for brevity.
...
}
这是中间件代码:
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
namespace RegistrationWeb.Middleware
{
public class ResponseWrapper
{
private readonly RequestDelegate _next;
public ResponseWrapper(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
var currentBody = context.Response.Body;
using (var memoryStream = new MemoryStream())
{
//set the current response to the memorystream.
context.Response.Body = memoryStream;
await _next(context);
//reset the body
context.Response.Body = currentBody;
memoryStream.Seek(0, SeekOrigin.Begin);
var readToEnd = new StreamReader(memoryStream).ReadToEnd();
var objResult = JsonConvert.DeserializeObject(readToEnd);
var result = CommonApiResponse.Create((HttpStatusCode)context.Response.StatusCode, objResult, null);
await context.Response.WriteAsync(JsonConvert.SerializeObject(result));
}
}
}
public static class ResponseWrapperExtensions
{
public static IApplicationBuilder UseResponseWrapper(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ResponseWrapper>();
}
}
public class CommonApiResponse
{
public static CommonApiResponse Create(HttpStatusCode statusCode, object result = null, string errorMessage = null)
{
return new CommonApiResponse(statusCode, result, errorMessage);
}
public string Version => "1.2.3";
public int StatusCode { get; set; }
public string RequestId { get; }
public string ErrorMessage { get; set; }
public object Result { get; set; }
protected CommonApiResponse(HttpStatusCode statusCode, object result = null, string errorMessage = null)
{
RequestId = Guid.NewGuid().ToString();
StatusCode = (int)statusCode;
Result = result;
ErrorMessage = errorMessage;
}
}
}
这篇关于如何包装 Web API 响应(在 .net 核心中)以保持一致性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!