Owin context.Response.Body始终为空

时间:2018-09-04 09:30:10

标签: c# asp.net-web-api asp.net-web-api2 owin owin-middleware

在调用next()之前,已经完成了一些示例并创建了一个新的缓冲区MemoryStream来替换Response.Body

下面是我的中间件:

public class TrackingMiddleware
{
    private readonly AppFunc next;

    public TrackingMiddleware(AppFunc next)
    {
        this.next = next;
    }

    public async Task Invoke(IDictionary<string, object> env)
    {
        IOwinContext context = new OwinContext(env);

        // Buffer the response
        var stream = context.Response.Body;
        var buffer = new MemoryStream();
        context.Response.Body = buffer;

        await this.next(env);

        buffer.Seek(0, SeekOrigin.Begin);
        var reader = new StreamReader(buffer);
        string responseBody = await reader.ReadToEndAsync();

        buffer.Seek(0, SeekOrigin.Begin);
        await buffer.CopyToAsync(stream);
    }
}

responsBody始终为空,如果我的ApiController的Action返回了数据列表。

下面是我的Owin Startup课程(我错过了什么吗?)

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    static Startup()
    {
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            Provider = new OAuthAppProvider(),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(2),
            AllowInsecureHttp = true
        };
    }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseOAuthBearerTokens(OAuthOptions);

        app.Use<TrackingMiddleware>();
    }
}

下面是我的ApiController

public class TestController : ApiController
{

    public IHttpActionResult Get()
    {
        return Json(new string[] {"123", "asdfsdf"});
    }
}

并且我的Web api配置是通过Global.asax.cs注册的。

public class WebApiApplication : System.Web.HttpApplication
{

    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

这是弄乱中间件顺序的原因吗?

或者,如果我使用MVC方法并且通过引用以下sample来与HttpContext.Current.Response一起使用

1 个答案:

答案 0 :(得分:0)

您必须将原始流放回响应中

context.Response.Body = stream;

这样,管道中的先前中间件就可以读取它

您还希望处置不再需要的任何资源

public async Task Invoke(IDictionary<string, object> env) {
    IOwinContext context = new OwinContext(env);

    // Buffer the response
    var stream = context.Response.Body;
    using (var buffer = new MemoryStream()) {
        context.Response.Body = buffer;

        //call next in pipeline
        await this.next(env);

        //reset the original response body
        context.Response.Body = stream;

        //get data from buffer
        buffer.Seek(0, SeekOrigin.Begin);
        var reader = new StreamReader(buffer);
        string responseBody = await reader.ReadToEndAsync();    
        buffer.Seek(0, SeekOrigin.Begin);

        //put data into original stream to continue the flow.
        await buffer.CopyToAsync(stream);
    }

}