From dd587f743b36009690cb24ba6d578e2e92a64b87 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 10 Oct 2014 17:54:20 -0700 Subject: [PATCH] [Fixes #1331] Dispose HttpResponseMessage once its written out in HttpResponseMessageOutputFormatter --- .../HttpResponseMessageOutputFormatter.cs | 35 +++++++------- ...HttpResponseMessageOutputFormatterTests.cs | 46 +++++++++++++++++++ 2 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpResponseMessageOutputFormatterTests.cs diff --git a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/Formatters/HttpResponseMessageOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/Formatters/HttpResponseMessageOutputFormatter.cs index 3dd743b842..0816da323b 100644 --- a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/Formatters/HttpResponseMessageOutputFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/Formatters/HttpResponseMessageOutputFormatter.cs @@ -40,29 +40,32 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim throw new InvalidOperationException(message); } - response.StatusCode = (int)responseMessage.StatusCode; - - var responseFeature = context.ActionContext.HttpContext.GetFeature(); - if (responseFeature != null) + using (responseMessage) { - responseFeature.ReasonPhrase = responseMessage.ReasonPhrase; - } + response.StatusCode = (int)responseMessage.StatusCode; - var responseHeaders = responseMessage.Headers; - foreach (var header in responseHeaders) - { - response.Headers.AppendValues(header.Key, header.Value.ToArray()); - } + var responseFeature = context.ActionContext.HttpContext.GetFeature(); + if (responseFeature != null) + { + responseFeature.ReasonPhrase = responseMessage.ReasonPhrase; + } - if (responseMessage.Content != null) - { - var contentHeaders = responseMessage.Content.Headers; - foreach (var header in contentHeaders) + var responseHeaders = responseMessage.Headers; + foreach (var header in responseHeaders) { response.Headers.AppendValues(header.Key, header.Value.ToArray()); } - await responseMessage.Content.CopyToAsync(response.Body); + if (responseMessage.Content != null) + { + var contentHeaders = responseMessage.Content.Headers; + foreach (var header in contentHeaders) + { + response.Headers.AppendValues(header.Key, header.Value.ToArray()); + } + + await responseMessage.Content.CopyToAsync(response.Body); + } } } } diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpResponseMessageOutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpResponseMessageOutputFormatterTests.cs new file mode 100644 index 0000000000..4c241ebf14 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpResponseMessageOutputFormatterTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNet.Mvc.WebApiCompatShim; +using Microsoft.AspNet.PipelineCore; +using Moq; +using Moq.Protected; +using Xunit; + +namespace Microsoft.AspNet.Mvc.WebApiCompatShimTest +{ + public class HttpResponseMessageOutputFormatterTests + { + [Fact] + public async Task Disposed_CalledOn_HttpResponseMessage() + { + // Arrange + var formatter = new HttpResponseMessageOutputFormatter(); + var streamContent = new Mock(new MemoryStream()); + streamContent.Protected().Setup("Dispose", true).Verifiable(); + var httpResponseMessage = new HttpResponseMessage(); + httpResponseMessage.Content = streamContent.Object; + var outputFormatterContext = GetOutputFormatterContext(httpResponseMessage, typeof(HttpResponseMessage)); + + // Act + await formatter.WriteAsync(outputFormatterContext); + + // Assert + streamContent.Protected().Verify("Dispose", Times.Once(), true); + } + + private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType) + { + return new OutputFormatterContext + { + Object = outputValue, + DeclaredType = outputType, + ActionContext = new ActionContext(new DefaultHttpContext(), routeData: null, actionDescriptor: null) + }; + } + } +} \ No newline at end of file