diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs index a9014a5bc2..aa3d1ec3a5 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs @@ -80,22 +80,32 @@ namespace Microsoft.AspNet.Mvc viewData = new ViewDataDictionary(modelMetadataProvider, context.ModelState); } - var contentType = ContentType ?? ViewExecutor.DefaultContentType; - if (contentType.Encoding == null) + 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; } + // 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(); + if (StatusCode != null) { response.StatusCode = StatusCode.Value; } - response.ContentType = contentType.ToString(); - - using (var writer = new HttpResponseStreamWriter(response.Body, contentType.Encoding)) + var encoding = contentType?.Encoding ?? ViewExecutor.DefaultContentType?.Encoding; + using (var writer = new HttpResponseStreamWriter(response.Body, encoding)) { var viewContext = new ViewContext( context, diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs index 4dda1eec05..6b0536d9e4 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs @@ -45,6 +45,10 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures contentType.Encoding = Encoding.UTF8; } + // 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(); using (var writer = new HttpResponseStreamWriter(response.Body, contentType?.Encoding ?? DefaultContentType.Encoding)) diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs index eb04ee9c16..a446394e59 100644 --- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs @@ -309,6 +309,65 @@ namespace Microsoft.AspNet.Mvc Assert.Equal(contentTypeBeforeViewResultExecution, contentTypeAfterViewResultExecution); } + [Fact] + public async Task ViewComponentResult_SetsContentTypeHeader_OverrideResponseContentType() + { + // Arrange + var descriptor = new ViewComponentDescriptor() + { + FullName = "Full.Name.Text", + ShortName = "Text", + Type = typeof(TextViewComponent), + }; + + var actionContext = CreateActionContext(descriptor); + + var expectedContentType = "text/html; charset=utf-8"; + actionContext.HttpContext.Response.ContentType = "application/x-will-be-overridden"; + + var viewComponentResult = new ViewComponentResult() + { + Arguments = new object[] { "World!" }, + ViewComponentName = "Text", + ContentType = new MediaTypeHeaderValue("text/html") { Encoding = Encoding.UTF8 }, + }; + + // Act + await viewComponentResult.ExecuteResultAsync(actionContext); + + // Assert + Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType); + } + + [Fact] + public async Task ViewComponentResult_NoContentTypeSet_PreservesResponseContentType() + { + // Arrange + var descriptor = new ViewComponentDescriptor() + { + FullName = "Full.Name.Text", + ShortName = "Text", + Type = typeof(TextViewComponent), + }; + + var actionContext = CreateActionContext(descriptor); + + var expectedContentType = "application/x-will-not-be-overridden"; + actionContext.HttpContext.Response.ContentType = expectedContentType; + + var viewComponentResult = new ViewComponentResult() + { + Arguments = new object[] { "World!" }, + ViewComponentName = "Text", + }; + + // Act + await viewComponentResult.ExecuteResultAsync(actionContext); + + // Assert + Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType); + } + private IServiceCollection CreateServices(params ViewComponentDescriptor[] descriptors) { var services = new ServiceCollection();