[Fixes #3177] Clean up logic for encoding in ViewResult and friends

This commit is contained in:
Kiran Challa 2015-10-21 12:35:24 -07:00
parent cd761a644d
commit 5364468001
14 changed files with 354 additions and 135 deletions

View File

@ -47,32 +47,31 @@ namespace Microsoft.AspNet.Mvc
var logger = loggerFactory.CreateLogger<ContentResult>();
var response = context.HttpContext.Response;
var contentTypeHeader = ContentType;
if (contentTypeHeader != null && contentTypeHeader.Encoding == null)
{
// Do not modify the user supplied content type, so copy it instead
contentTypeHeader = contentTypeHeader.Copy();
contentTypeHeader.Encoding = Encoding.UTF8;
}
string resolvedContentType;
Encoding resolvedContentTypeEncoding;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
ContentType,
response.ContentType,
DefaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
response.ContentType = contentTypeHeader?.ToString()
?? response.ContentType
?? DefaultContentType.ToString();
response.ContentType = resolvedContentType;
if (StatusCode != null)
{
response.StatusCode = StatusCode.Value;
}
logger.ContentResultExecuting(contentTypeHeader);
logger.ContentResultExecuting(resolvedContentType);
if (Content != null)
{
var bufferingFeature = response.HttpContext.Features.Get<IHttpBufferingFeature>();
bufferingFeature?.DisableResponseBuffering();
return response.WriteAsync(Content, contentTypeHeader?.Encoding ?? DefaultContentType.Encoding);
return response.WriteAsync(Content, resolvedContentTypeEncoding);
}
return TaskCache.CompletedTask;

View File

@ -0,0 +1,73 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Text;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Mvc.Internal
{
public static class ResponseContentTypeHelper
{
/// <summary>
/// Gets the content type and encoding that need to be used for the response.
/// The priority for selecting the content type is:
/// 1. ContentType property set on the action result
/// 2. <see cref="HttpResponse.ContentType"/> property set on <see cref="HttpResponse"/>
/// 3. Default content type set on the action result
/// </summary>
/// <remarks>
/// The user supplied content type is not modified and is used as is. For example, if user
/// sets the content type to be "text/plain" without any encoding, then the default content type's
/// encoding is used to write the response and the ContentType header is set to be "text/plain" without any
/// "charset" information.
/// </remarks>
/// <param name="actionResultContentType">ContentType set on the action result</param>
/// <param name="httpResponseContentType"><see cref="HttpResponse.ContentType"/> property set
/// on <see cref="HttpResponse"/></param>
/// <param name="defaultContentType">The default content type of the action result.</param>
/// <param name="resolvedContentType">The content type to be used for the response content type header</param>
/// <param name="resolvedContentTypeEncoding">Encoding to be used for writing the response</param>
public static void ResolveContentTypeAndEncoding(
MediaTypeHeaderValue actionResultContentType,
string httpResponseContentType,
MediaTypeHeaderValue defaultContentType,
out string resolvedContentType,
out Encoding resolvedContentTypeEncoding)
{
Debug.Assert(defaultContentType != null);
Debug.Assert(defaultContentType.Encoding != null);
// 1. User sets the ContentType property on the action result
if (actionResultContentType != null)
{
resolvedContentType = actionResultContentType.ToString();
resolvedContentTypeEncoding = actionResultContentType.Encoding ?? defaultContentType.Encoding;
return;
}
// 2. User sets the ContentType property on the http response directly
if (!string.IsNullOrEmpty(httpResponseContentType))
{
MediaTypeHeaderValue mediaType;
if (MediaTypeHeaderValue.TryParse(httpResponseContentType, out mediaType))
{
resolvedContentType = httpResponseContentType;
resolvedContentTypeEncoding = mediaType.Encoding ?? defaultContentType.Encoding;
}
else
{
resolvedContentType = httpResponseContentType;
resolvedContentTypeEncoding = defaultContentType.Encoding;
}
return;
}
// 3. Fall-back to the default content type
resolvedContentType = defaultContentType.ToString();
resolvedContentTypeEncoding = defaultContentType.Encoding;
}
}
}

View File

@ -19,9 +19,9 @@ namespace Microsoft.AspNet.Mvc.Logging
"Executing ContentResult with HTTP Response ContentType of {ContentType}");
}
public static void ContentResultExecuting(this ILogger logger, MediaTypeHeaderValue contentType)
public static void ContentResultExecuting(this ILogger logger, string contentType)
{
_contentResultExecuting(logger, contentType?.MediaType, null);
_contentResultExecuting(logger, contentType, null);
}
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
@ -79,22 +80,16 @@ namespace Microsoft.AspNet.Mvc
var response = context.HttpContext.Response;
var contentTypeHeader = ContentType;
if (contentTypeHeader == null)
{
contentTypeHeader = DefaultContentType;
}
else
{
if (contentTypeHeader.Encoding == null)
{
// Do not modify the user supplied content type, so copy it instead
contentTypeHeader = contentTypeHeader.Copy();
contentTypeHeader.Encoding = Encoding.UTF8;
}
}
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
ContentType,
response.ContentType,
DefaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
response.ContentType = contentTypeHeader.ToString();
response.ContentType = resolvedContentType;
if (StatusCode != null)
{
@ -113,8 +108,7 @@ namespace Microsoft.AspNet.Mvc
}
logger.JsonResultExecuting(Value);
using (var writer = new HttpResponseStreamWriter(response.Body, contentTypeHeader.Encoding))
using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
{
using (var jsonWriter = new JsonTextWriter(writer))
{

View File

@ -4,6 +4,7 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
@ -90,32 +91,23 @@ namespace Microsoft.AspNet.Mvc
tempData = services.GetRequiredService<ITempDataDictionary>();
}
var contentType = ContentType;
if (contentType != null && contentType.Encoding == null)
{
// Do not modify the user supplied content type, so copy it instead
contentType = contentType.Copy();
contentType.Encoding = Encoding.UTF8;
}
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
ContentType,
response.ContentType,
ViewExecutor.DefaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
// Priority list for setting content-type/encoding:
// 1. this.ContentType (set by the user on the result)
// 2. response.ContentType (likely set by the user in controller code)
// 3. ViewExecutor.DefaultContentType (sensible default)
//
//
response.ContentType =
contentType?.ToString() ??
response.ContentType ??
ViewExecutor.DefaultContentType.ToString();
response.ContentType = resolvedContentType;
if (StatusCode != null)
{
response.StatusCode = StatusCode.Value;
}
var encoding = contentType?.Encoding ?? ViewExecutor.DefaultContentType?.Encoding;
using (var writer = new HttpResponseStreamWriter(response.Body, encoding))
using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
{
var viewContext = new ViewContext(
context,

View File

@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Diagnostics;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
@ -96,7 +97,8 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
/// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param>
/// <param name="tempData">The <see cref="ITempDataDictionary"/>.</param>
/// <param name="contentType">
/// The content-type header value to set in the response. If <c>null</c>, <see cref="DefaultContentType"/> will be used.
/// The content-type header value to set in the response. If <c>null</c>,
/// <see cref="DefaultContentType"/> will be used.
/// </param>
/// <param name="statusCode">
/// The HTTP status code to set in the response. May be <c>null</c>.
@ -134,26 +136,23 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
var response = actionContext.HttpContext.Response;
if (contentType != null && contentType.Encoding == null)
{
// Do not modify the user supplied content type, so copy it instead
contentType = contentType.Copy();
contentType.Encoding = Encoding.UTF8;
}
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
contentType,
response.ContentType,
DefaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
// Priority list for setting content-type:
// 1. passed in contentType (likely set by the user on the result)
// 2. response.ContentType (likely set by the user in controller code)
// 3. ViewExecutor.DefaultContentType (sensible default)
response.ContentType = contentType?.ToString() ?? response.ContentType ?? DefaultContentType.ToString();
response.ContentType = resolvedContentType;
if (statusCode != null)
{
response.StatusCode = statusCode.Value;
}
var encoding = contentType?.Encoding ?? DefaultContentType.Encoding;
using (var writer = WriterFactory.CreateWriter(response.Body, encoding))
using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding))
{
var viewContext = new ViewContext(
actionContext,
@ -162,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
tempData,
writer,
ViewOptions.HtmlHelperOptions);
DiagnosticSource.BeforeView(view, viewContext);
await view.RenderAsync(viewContext);

View File

@ -22,47 +22,6 @@ namespace Microsoft.AspNet.Mvc
{
public class ContentResultTest
{
[Fact]
public async Task ContentResult_Response_NullEncoding_SetsContentTypeAndDefaultEncoding()
{
// Arrange
var contentResult = new ContentResult
{
Content = "Test Content",
ContentType = new MediaTypeHeaderValue("application/json")
};
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
// Act
await contentResult.ExecuteResultAsync(actionContext);
// Assert
Assert.Equal("application/json; charset=utf-8", httpContext.Response.ContentType);
}
[Fact]
public async Task ContentResult_Response_SetsContentTypeAndEncoding()
{
// Arrange
var contentResult = new ContentResult
{
Content = "Test Content",
ContentType = new MediaTypeHeaderValue("text/plain")
{
Encoding = Encoding.ASCII
}
};
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
// Act
await contentResult.ExecuteResultAsync(actionContext);
// Assert
Assert.Equal("text/plain; charset=us-ascii", httpContext.Response.ContentType);
}
[Fact]
public async Task ContentResult_Response_NullContent_SetsContentTypeAndEncoding()
{
@ -118,6 +77,7 @@ namespace Microsoft.AspNet.Mvc
{
get
{
// contentType, content, responseContentType, expectedContentType, expectedData
return new TheoryData<MediaTypeHeaderValue, string, string, string, byte[]>
{
{
@ -131,14 +91,14 @@ namespace Microsoft.AspNet.Mvc
new MediaTypeHeaderValue("text/foo"),
"κόσμε",
null,
"text/foo; charset=utf-8",
"text/foo",
new byte[] { 206, 186, 225, 189, 185, 207, 131, 206, 188, 206, 181 } //utf-8 without BOM
},
{
MediaTypeHeaderValue.Parse("text/foo;p1=p1-value"),
"κόσμε",
null,
"text/foo; p1=p1-value; charset=utf-8",
"text/foo; p1=p1-value",
new byte[] { 206, 186, 225, 189, 185, 207, 131, 206, 188, 206, 181 } //utf-8 without BOM
},
{

View File

@ -0,0 +1,143 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNet.Mvc.Internal
{
public class ResponseContentTypeHelperTest
{
public static TheoryData<MediaTypeHeaderValue, string, string> ResponseContentTypeData
{
get
{
// contentType, responseContentType, expectedContentType
return new TheoryData<MediaTypeHeaderValue, string, string>
{
// No explicit content type is provided, fall-back to the default content type
{
null,
null,
"text/default; p1=p1-value; charset=utf-8"
},
// Content type is set explicitly without encoding on action result. No charset parameter added in
// expected content type
{
new MediaTypeHeaderValue("text/foo"),
null,
"text/foo"
},
// Content type is set explicitly with encoding on action result. Expected content type
// has the charset
{
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
null,
"text/foo; charset=us-ascii"
},
// Content type is set explicitly without encoding and additional parameters on action result
// Expected content type has the additional parameters but with no charset.
{
MediaTypeHeaderValue.Parse("text/foo; p1=p1-value"),
null,
"text/foo; p1=p1-value"
},
// Content type is set explicitly with encoding and additional parameters on action result
// Expected content type has the additional parameters and the charset.
{
MediaTypeHeaderValue.Parse("text/foo; p1=p1-value; charset=us-ascii"),
null,
"text/foo; p1=p1-value; charset=us-ascii"
},
// Content type is set explicitly without encoding on http response.
// No charset parameter added in expected content type
{
null,
"text/bar",
"text/bar"
},
// Content type is set explicitly without encoding and additional parameters on http response
// No charset parameter added in expected content type
{
null,
"text/bar; p1=p1-value",
"text/bar; p1=p1-value"
},
// Content type is set explicitly with encoding and additional parameters on http response
// Expected content type has charset and additional parameters
{
null,
"text/bar; p1=p1-value; charset=us-ascii",
"text/bar; p1=p1-value; charset=us-ascii"
},
// Content type set on action result takes precedence over the conten type set on http response
{
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
"text/bar",
"text/foo; charset=us-ascii"
},
{
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
"text/bar; charset=utf-8",
"text/foo; charset=us-ascii"
}
};
}
}
[Theory]
[MemberData(nameof(ResponseContentTypeData))]
public void GetsExpectedContentTypeAndEncoding(
MediaTypeHeaderValue contentType,
string responseContentType,
string expectedContentType)
{
// Arrange
var defaultContentType = MediaTypeHeaderValue.Parse("text/default; p1=p1-value; charset=utf-8");
// Act
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
contentType,
responseContentType,
defaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
// Assert
Assert.Equal(expectedContentType, resolvedContentType);
}
[Fact]
public void DoesNotThrowException_OnInvalidResponseContentType()
{
// Arrange
var expectedContentType = "invalid-content-type";
var defaultContentType = MediaTypeHeaderValue.Parse("text/plain; charset=utf-8");
// Act
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
null,
expectedContentType,
defaultContentType,
out resolvedContentType,
out resolvedContentTypeEncoding);
// Assert
Assert.Equal(expectedContentType, resolvedContentType);
Assert.Equal(Encoding.UTF8, resolvedContentTypeEncoding);
}
}
}

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Mvc
}
[Fact]
public async Task ExecuteResultAsync_NullEncoding_SetsContentTypeAndDefaultEncoding()
public async Task ExecuteResultAsync_NullEncoding_DoesNotSetCharsetOnContentType()
{
// Arrange
var expected = _abcdUTF8Bytes;
@ -62,7 +62,7 @@ namespace Microsoft.AspNet.Mvc
// Assert
Assert.Equal(expected, written);
Assert.Equal("text/json; charset=utf-8", context.Response.ContentType);
Assert.Equal("text/json", context.Response.ContentType);
}
[Fact]
@ -89,6 +89,52 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal("text/json; charset=us-ascii", context.Response.ContentType);
}
[Fact]
public async Task NoResultContentTypeSet_UsesResponseContentType_AndSuppliedEncoding()
{
// Arrange
var expectedData = Encoding.ASCII.GetBytes("{\"foo\":\"abcd\"}");
var expectedContentType = "text/foo; p1=p1-value; charset=us-ascii";
var context = GetHttpContext();
context.Response.ContentType = expectedContentType;
var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
var result = new JsonResult(new { foo = "abcd" });
// Act
await result.ExecuteResultAsync(actionContext);
var written = GetWrittenBytes(context);
// Assert
Assert.Equal(expectedData, written);
Assert.Equal(expectedContentType, context.Response.ContentType);
}
[Theory]
[InlineData("text/foo", "text/foo")]
[InlineData("text/foo; p1=p1-value", "text/foo; p1=p1-value")]
public async Task NoResultContentTypeSet_UsesResponseContentTypeAndDefaultEncoding_DoesNotSetCharset(
string responseContentType,
string expectedContentType)
{
// Arrange
var expected = _abcdUTF8Bytes;
var context = GetHttpContext();
context.Response.ContentType = responseContentType;
var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
var result = new JsonResult(new { foo = "abcd" });
// Act
await result.ExecuteResultAsync(actionContext);
var written = GetWrittenBytes(context);
// Assert
Assert.Equal(expected, written);
Assert.Equal(expectedContentType, context.Response.ContentType);
}
private static List<byte> AbcdIndentedUTF8Bytes
{
get

View File

@ -201,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
}
[Fact]
public async Task ContentResult_WritesContent_SetsContentTypeWithDefaultEncoding()
public async Task ContentResult_WritesContent_SetsContentType_UsesDefaultEncoding_AndNoCharset()
{
// Arrange
var request = new HttpRequestMessage(
@ -214,7 +214,6 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
Assert.Equal("utf-8", response.Content.Headers.ContentType.CharSet);
Assert.Equal("content", await response.Content.ReadAsStringAsync());
}

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc
};
var actionContext = CreateActionContext(descriptor);
var viewComponentResult = new ViewComponentResult
{
Arguments = new object[] { "World!" },
@ -338,11 +338,11 @@ namespace Microsoft.AspNet.Mvc
},
{
new MediaTypeHeaderValue("text/foo"),
"text/foo; charset=utf-8"
"text/foo"
},
{
MediaTypeHeaderValue.Parse("text/foo;p1=p1-value"),
"text/foo; p1=p1-value; charset=utf-8"
"text/foo; p1=p1-value"
},
{
new MediaTypeHeaderValue("text/foo") { Encoding = Encoding.ASCII },
@ -422,8 +422,13 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType);
}
[Fact]
public async Task ViewComponentResult_NoContentTypeSet_PreservesResponseContentType()
[Theory]
[InlineData("text/foo", "text/foo; charset=utf-8")]
[InlineData("text/foo; p1=p1-value", "text/foo; p1=p1-value; charset=utf-8")]
[InlineData("text/foo; p1=p1-value; charset=us-ascii", "text/foo; p1=p1-value; charset=us-ascii")]
public async Task ViewComponentResult_NoContentTypeSet_PreservesResponseContentType(
string responseContentType,
string expectedContentType)
{
// Arrange
var descriptor = new ViewComponentDescriptor()
@ -435,7 +440,6 @@ namespace Microsoft.AspNet.Mvc
var actionContext = CreateActionContext(descriptor);
var expectedContentType = "application/x-will-not-be-overridden";
actionContext.HttpContext.Response.ContentType = expectedContentType;
var viewComponentResult = new ViewComponentResult()
@ -453,7 +457,7 @@ namespace Microsoft.AspNet.Mvc
}
private IServiceCollection CreateServices(object diagnosticListener, HttpContext context, params ViewComponentDescriptor[] descriptors)
{
{
var httpContext = new HttpContextAccessor() { HttpContext = context };
var tempDataProvider = new SessionStateTempDataProvider();
var diagnosticSource = new DiagnosticListener("Microsoft.AspNet");

View File

@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
// Assert
Assert.Equal(viewName, viewEngineResult.ViewName);
}
[Fact]
public void FindView_WritesDiagnostic_ViewFound()
{
@ -163,7 +163,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
await executor.ExecuteAsync(context, Mock.Of<IView>(), viewResult);
// Assert
Assert.Equal("application/x-my-content-type; charset=utf-8", context.HttpContext.Response.ContentType);
Assert.Equal("application/x-my-content-type", context.HttpContext.Response.ContentType);
// Check if the original instance provided by the user has not changed.
// Since we do not have access to the new instance created within the view executor,
@ -199,7 +199,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
{
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
}
private PartialViewResultExecutor GetViewExecutor(DiagnosticSource diagnosticSource = null)
{
if (diagnosticSource == null)

View File

@ -38,17 +38,22 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
{
new MediaTypeHeaderValue("text/foo"),
null,
"text/foo; charset=utf-8"
"text/foo"
},
{
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
null,
"text/foo; charset=us-ascii"
},
{
MediaTypeHeaderValue.Parse("text/foo; p1=p1-value"),
null,
"text/foo; p1=p1-value; charset=utf-8"
"text/foo; p1=p1-value"
},
{
new MediaTypeHeaderValue("text/foo") { Charset = "us-ascii" },
MediaTypeHeaderValue.Parse("text/foo; p1=p1-value; charset=us-ascii"),
null,
"text/foo; charset=us-ascii"
"text/foo; p1=p1-value; charset=us-ascii"
},
{
null,
@ -57,19 +62,24 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
},
{
null,
"application/xml; charset=us-ascii",
"application/xml; charset=us-ascii"
"text/bar; p1=p1-value",
"text/bar; p1=p1-value"
},
{
{
null,
"Invalid content type",
"Invalid content type"
"text/bar; p1=p1-value; charset=us-ascii",
"text/bar; p1=p1-value; charset=us-ascii"
},
{
new MediaTypeHeaderValue("text/foo") { Charset = "us-ascii" },
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
"text/bar",
"text/foo; charset=us-ascii"
},
{
MediaTypeHeaderValue.Parse("text/foo; charset=us-ascii"),
"text/bar; charset=utf-8",
"text/foo; charset=us-ascii"
}
};
}
}
@ -150,7 +160,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
context,
new RouteData(),
new ActionDescriptor());
context.RequestServices = GetServiceProvider();
var viewExecutor = CreateViewExecutor();

View File

@ -163,7 +163,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
await executor.ExecuteAsync(context, Mock.Of<IView>(), viewResult);
// Assert
Assert.Equal("application/x-my-content-type; charset=utf-8", context.HttpContext.Response.ContentType);
Assert.Equal("application/x-my-content-type", context.HttpContext.Response.ContentType);
// Check if the original instance provided by the user has not changed.
// Since we do not have access to the new instance created within the view executor,
@ -199,7 +199,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
{
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
}
private ViewResultExecutor GetViewExecutor(DiagnosticListener diagnosticSource = null)
{
if (diagnosticSource == null)