diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
index e08443c6b0..81ef066f9d 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
@@ -177,6 +177,9 @@ namespace Microsoft.AspNet.Mvc
throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
}
+ // Clone the media type as we don't want it to affect the next request
+ selectedMediaType = MediaTypeHeaderValue.Parse(selectedMediaType.ToString());
+
var selectedEncoding = SelectCharacterEncoding(context);
if (selectedEncoding == null)
{
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
index e2e7cbe1f1..80e90c72d7 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
@@ -120,6 +120,29 @@ namespace Microsoft.AspNet.Mvc.Test
formatterContext.SelectedContentType.ToString());
}
+ [Fact]
+ public async Task WriteResponseHeaders_ClonesMediaType()
+ {
+ // Arrange
+ var formatter = new PngImageFormatter();
+ formatter.SupportedMediaTypes.Clear();
+ var mediaType = new MediaTypeHeaderValue("image/png");
+ formatter.SupportedMediaTypes.Add(mediaType);
+ var formatterContext = new OutputFormatterContext();
+ formatterContext.ActionContext = new ActionContext(
+ new DefaultHttpContext(),
+ new RouteData(),
+ new ActionDescriptor());
+
+ // Act
+ await formatter.WriteAsync(formatterContext);
+
+ // Assert
+ Assert.NotSame(mediaType, formatterContext.SelectedContentType);
+ Assert.Null(mediaType.Charset);
+ Assert.Equal("image/png; charset=utf-8", formatterContext.SelectedContentType.ToString());
+ }
+
[Fact]
public void CanWriteResult_ForNullContentType_UsesFirstEntryInSupportedContentTypes()
{
@@ -294,7 +317,7 @@ namespace Microsoft.AspNet.Mvc.Test
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
{
// Do not set the selected media Type.
- // The WriteResponseContentHeader should do it for you.
+ // The WriteResponseHeaders should do it for you.
return true;
}
@@ -303,5 +326,19 @@ namespace Microsoft.AspNet.Mvc.Test
return Task.FromResult(true);
}
}
+
+ private class PngImageFormatter : OutputFormatter
+ {
+ public PngImageFormatter()
+ {
+ SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("image/png"));
+ SupportedEncodings.Add(Encoding.UTF8);
+ }
+
+ public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
+ {
+ return Task.FromResult(true);
+ }
+ }
}
}
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ConnegTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ConnegTests.cs
index d9c3f0e892..cadcbeb8d9 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/ConnegTests.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ConnegTests.cs
@@ -296,6 +296,50 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal(expectedBody, body);
}
+ [Fact]
+ public async Task JsonFormatter_SupportedMediaType_DoesNotChangeAcrossRequests()
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+ var expectedContentType = MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
+ var expectedBody = "{\"MethodName\":\"ReturnJsonResult\"}";
+
+ for (int i = 0; i < 5; i++)
+ {
+ // Act and Assert
+ var response = await client.GetAsync("http://localhost/JsonResult/ReturnJsonResult");
+
+ Assert.Equal(expectedContentType, response.Content.Headers.ContentType);
+ var body = await response.Content.ReadAsStringAsync();
+ Assert.Equal(expectedBody, body);
+ }
+ }
+
+ [Fact]
+ public async Task XmlFormatter_SupportedMediaType_DoesNotChangeAcrossRequests()
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+ client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
+ client.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
+ var expectedContentType = MediaTypeHeaderValue.Parse("application/xml;charset=utf-8");
+ var expectedBody = @""
+ + @"One Microsoft WayJohn";
+
+ for (int i = 0; i < 5; i++)
+ {
+ // Act and Assert
+ var response = await client.GetAsync("http://localhost/Home/UserInfo");
+
+ Assert.Equal(expectedContentType, response.Content.Headers.ContentType);
+ var body = await response.Content.ReadAsStringAsync();
+ Assert.Equal(expectedBody, body);
+ }
+ }
+
[Theory]
[InlineData("UseTheFallback_WithDefaultFormatters")]
[InlineData("UseTheFallback_UsingCustomFormatters")]
diff --git a/test/WebSites/ConnegWebSite/Controllers/HomeController.cs b/test/WebSites/ConnegWebSite/Controllers/HomeController.cs
index 56307aa2fe..e54e8e8ad0 100644
--- a/test/WebSites/ConnegWebSite/Controllers/HomeController.cs
+++ b/test/WebSites/ConnegWebSite/Controllers/HomeController.cs
@@ -11,5 +11,10 @@ namespace ConnegWebSite
{
return new JsonResult("Index Method");
}
+
+ public User UserInfo()
+ {
+ return new User() { Name = "John", Address = "One Microsoft Way" };
+ }
}
}
\ No newline at end of file
diff --git a/test/WebSites/ConnegWebSite/Startup.cs b/test/WebSites/ConnegWebSite/Startup.cs
index 8901654343..fd4e143ecf 100644
--- a/test/WebSites/ConnegWebSite/Startup.cs
+++ b/test/WebSites/ConnegWebSite/Startup.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder;
+using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
@@ -18,8 +19,13 @@ namespace ConnegWebSite
{
// Add MVC services to the services container
services.AddMvc(configuration);
- });
+ services.Configure(options =>
+ {
+ options.AddXmlDataContractSerializerFormatter();
+ });
+ });
+
// Add MVC to the request pipeline
app.UseMvc(routes =>
{