Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit 35e0720

Browse files
committed
[Fixes #1331] Dispose HttpResponseMessage once its written out in HttpResponseMessageOutputFormatter
1 parent 13ee27c commit 35e0720

File tree

2 files changed

+76
-16
lines changed

2 files changed

+76
-16
lines changed

src/Microsoft.AspNet.Mvc.WebApiCompatShim/Formatters/HttpResponseMessageOutputFormatter.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,32 @@ public async Task WriteAsync(OutputFormatterContext context)
4040
throw new InvalidOperationException(message);
4141
}
4242

43-
response.StatusCode = (int)responseMessage.StatusCode;
44-
45-
var responseFeature = context.ActionContext.HttpContext.GetFeature<IHttpResponseFeature>();
46-
if (responseFeature != null)
43+
using (responseMessage)
4744
{
48-
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
49-
}
45+
response.StatusCode = (int)responseMessage.StatusCode;
5046

51-
var responseHeaders = responseMessage.Headers;
52-
foreach (var header in responseHeaders)
53-
{
54-
response.Headers.AppendValues(header.Key, header.Value.ToArray());
55-
}
47+
var responseFeature = context.ActionContext.HttpContext.GetFeature<IHttpResponseFeature>();
48+
if (responseFeature != null)
49+
{
50+
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
51+
}
5652

57-
if (responseMessage.Content != null)
58-
{
59-
var contentHeaders = responseMessage.Content.Headers;
60-
foreach (var header in contentHeaders)
53+
var responseHeaders = responseMessage.Headers;
54+
foreach (var header in responseHeaders)
6155
{
6256
response.Headers.AppendValues(header.Key, header.Value.ToArray());
6357
}
6458

65-
await responseMessage.Content.CopyToAsync(response.Body);
59+
if (responseMessage.Content != null)
60+
{
61+
var contentHeaders = responseMessage.Content.Headers;
62+
foreach (var header in contentHeaders)
63+
{
64+
response.Headers.AppendValues(header.Key, header.Value.ToArray());
65+
}
66+
67+
await responseMessage.Content.CopyToAsync(response.Body);
68+
}
6669
}
6770
}
6871
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.IO;
6+
using System.Net.Http;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNet.Http;
9+
using Microsoft.AspNet.Mvc.WebApiCompatShim;
10+
using Moq;
11+
using Moq.Protected;
12+
using Xunit;
13+
14+
namespace Microsoft.AspNet.Mvc.WebApiCompatShimTest
15+
{
16+
public class HttpResponseMessageOutputFormatterTests
17+
{
18+
[Fact]
19+
public async Task Disposed_CalledOn_HttpResponseMessage()
20+
{
21+
// Arrange
22+
var formatter = new HttpResponseMessageOutputFormatter();
23+
var streamContent = new Mock<StreamContent>(new MemoryStream());
24+
streamContent.Protected().Setup("Dispose", true).Verifiable();
25+
var httpResponseMessage = new HttpResponseMessage();
26+
httpResponseMessage.Content = streamContent.Object;
27+
var outputFormatterContext = GetOutputFormatterContext(httpResponseMessage, typeof(HttpResponseMessage));
28+
29+
// Act
30+
await formatter.WriteAsync(outputFormatterContext);
31+
32+
// Assert
33+
streamContent.Protected().Verify("Dispose", Times.Once(), true);
34+
}
35+
36+
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType)
37+
{
38+
return new OutputFormatterContext
39+
{
40+
Object = outputValue,
41+
DeclaredType = outputType,
42+
ActionContext = GetActionContext()
43+
};
44+
}
45+
46+
private static ActionContext GetActionContext()
47+
{
48+
var request = new Mock<HttpRequest>();
49+
var response = new Mock<HttpResponse>();
50+
response.SetupGet(f => f.Body).Returns(new MemoryStream());
51+
var httpContext = new Mock<HttpContext>();
52+
httpContext.SetupGet(c => c.Request).Returns(request.Object);
53+
httpContext.SetupGet(c => c.Response).Returns(response.Object);
54+
return new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)