C# DotNet 核心中间件包装响应 [英] C# DotNet Core Middleware Wrap Response

查看:25
本文介绍了C# DotNet 核心中间件包装响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的控制器操作,如下所示:

I have a simple controller action which looks like:

    public Task<IEnumerable<Data>> GetData()
    {
        IEnumerable<Data> data = new List<Data>();
        return data;
    }

我希望能够检查中间件中的返回值,以便 JSON 看起来像

I want to be able to inspect the return value from within the middleware so the JSON would look something like

{
  "data": [
  ],
  "apiVersion": "1.2",
  "otherInfoHere": "here"
}

所以我的有效载荷总是在 data 内.我知道我可以在控制器级别执行此操作,但我不想在每个操作上都执行此操作.我宁愿在中间件中做一次.

So my payload always is within data. I know I can do this at a controller level but I don't wan to have to do it on every single action. I would rather do it in middleware once for all.

这是我的中间件示例:

public class NormalResponseWrapper
{
    private readonly RequestDelegate next;

    public NormalResponseWrapper(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {                
        var obj = context;
        // DO something to get return value from obj
        // Create payload and set data to return value

        await context.Response.WriteAsync(/*RETURN NEW PAYLOAD HERE*/);
    }

有什么想法吗?

现在得到了价值,但归还为时已晚

        try
        {
            using (var memStream = new MemoryStream())
            {
                context.Response.Body = memStream;
                await next(context);
                memStream.Position = 0;
                object responseBody = new StreamReader(memStream).ReadToEnd();
                memStream.Position = 0;
                await memStream.CopyToAsync(originalBody);
                // By now it is to late, above line sets the value that is going to be returned
                await context.Response.WriteAsync(new BaseResponse() { data = responseBody }.toJson());
            }

        }
        finally
        {
            context.Response.Body = originalBody;
        }

推荐答案

查看评论以了解您可以做什么来包装响应.

Review the comments to get an understanding of what you can do to wrap the response.

public async Task Invoke(HttpContext context) {
    //Hold on to original body for downstream calls
    Stream originalBody = context.Response.Body;
    try {
        string responseBody = null;
        using (var memStream = new MemoryStream()) {
            //Replace stream for upstream calls.
            context.Response.Body = memStream;
            //continue up the pipeline
            await next(context);
            //back from upstream call.
            //memory stream now hold the response data
            //reset position to read data stored in response stream
            memStream.Position = 0;
            responseBody = new StreamReader(memStream).ReadToEnd();
        }//dispose of previous memory stream.
        //lets convert responseBody to something we can use
        var data = JsonConvert.DeserializeObject(responseBody);
        //create your wrapper response and convert to JSON
        var json = new BaseResponse() { 
            data = data, 
            apiVersion = "1.2",
            otherInfoHere = "here"
        }.toJson();
        //convert json to a stream
        var buffer = Encoding.UTF8.GetBytes(json);
        using(var output = new MemoryStream(buffer)) {
            await output.CopyToAsync(originalBody);
        }//dispose of output stream
    } finally {
        //and finally, reset the stream for downstream calls
        context.Response.Body = originalBody;
    }
} 

这篇关于C# DotNet 核心中间件包装响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆