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

Commit 45346db

Browse files
committed
Use strongly typed MediaTypeHeaderValue for content type in action results.
1 parent 584015c commit 45346db

24 files changed

+532
-166
lines changed

samples/MvcSample.Web/Filters/ErrorMessagesAttribute.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using Microsoft.AspNet.Mvc;
5+
using Microsoft.Net.Http.Headers;
56

67
namespace MvcSample.Web
78
{
@@ -15,7 +16,7 @@ public override void OnActionExecuted(ActionExecutedContext context)
1516

1617
context.Result = new ContentResult
1718
{
18-
ContentType = "text/plain",
19+
ContentType = new MediaTypeHeaderValue("text/plain"),
1920
Content = "Boom " + context.Exception.Message
2021
};
2122
}

src/Microsoft.AspNet.Mvc.Core/ActionResults/ContentResult.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
5+
using System.IO;
46
using System.Text;
57
using System.Threading.Tasks;
68
using Microsoft.AspNet.Http;
@@ -11,11 +13,17 @@ namespace Microsoft.AspNet.Mvc
1113
{
1214
public class ContentResult : ActionResult
1315
{
14-
public string Content { get; set; }
16+
private readonly MediaTypeHeaderValue DefaultContentType = new MediaTypeHeaderValue("text/plain")
17+
{
18+
Encoding = Encoding.UTF8
19+
};
1520

16-
public Encoding ContentEncoding { get; set; }
21+
public string Content { get; set; }
1722

18-
public string ContentType { get; set; }
23+
/// <summary>
24+
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
25+
/// </summary>
26+
public MediaTypeHeaderValue ContentType { get; set; }
1927

2028
/// <summary>
2129
/// Gets or sets the HTTP status code.
@@ -26,17 +34,26 @@ public override async Task ExecuteResultAsync([NotNull] ActionContext context)
2634
{
2735
var response = context.HttpContext.Response;
2836

29-
MediaTypeHeaderValue contentTypeHeader;
30-
if (string.IsNullOrEmpty(ContentType))
37+
var contentTypeHeader = ContentType;
38+
Encoding encoding;
39+
if (contentTypeHeader == null)
3140
{
32-
contentTypeHeader = new MediaTypeHeaderValue("text/plain");
41+
contentTypeHeader = DefaultContentType;
42+
encoding = DefaultContentType.Encoding;
3343
}
3444
else
3545
{
36-
contentTypeHeader = new MediaTypeHeaderValue(ContentType);
46+
if (contentTypeHeader.Encoding == null)
47+
{
48+
// 1. Do not modify the user supplied content type
49+
// 2. Parse here to handle parameters apart from charset
50+
contentTypeHeader = MediaTypeHeaderValue.Parse(contentTypeHeader.ToString());
51+
contentTypeHeader.Encoding = Encoding.UTF8;
52+
}
53+
54+
encoding = contentTypeHeader.Encoding;
3755
}
3856

39-
contentTypeHeader.Encoding = ContentEncoding ?? Encodings.UTF8EncodingWithoutBOM;
4057
response.ContentType = contentTypeHeader.ToString();
4158

4259
if (StatusCode != null)
@@ -46,7 +63,7 @@ public override async Task ExecuteResultAsync([NotNull] ActionContext context)
4663

4764
if (Content != null)
4865
{
49-
await response.WriteAsync(Content, contentTypeHeader.Encoding);
66+
await response.WriteAsync(Content, encoding);
5067
}
5168
}
5269
}

src/Microsoft.AspNet.Mvc.Core/ActionResults/FileContentResult.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77
using Microsoft.AspNet.Http;
88
using Microsoft.Framework.Internal;
9+
using Microsoft.Net.Http.Headers;
910

1011
namespace Microsoft.AspNet.Mvc
1112
{
@@ -19,13 +20,14 @@ public class FileContentResult : FileResult
1920

2021
/// <summary>
2122
/// Creates a new <see cref="FileContentResult"/> instance with
22-
/// the provided <paramref name="fileContents"/>.
23+
/// the provided <paramref name="fileContents"/> and the
24+
/// provided <paramref name="contentType"/>.
2325
/// </summary>
2426
/// <param name="fileContents">The bytes that represent the file contents.</param>
25-
public FileContentResult([NotNull] byte[] fileContents)
26-
: base(contentType: null)
27+
/// <param name="contentType">The Content-Type header of the response.</param>
28+
public FileContentResult([NotNull] byte[] fileContents, string contentType)
29+
: this(fileContents, new MediaTypeHeaderValue(contentType))
2730
{
28-
FileContents = fileContents;
2931
}
3032

3133
/// <summary>
@@ -35,7 +37,7 @@ public FileContentResult([NotNull] byte[] fileContents)
3537
/// </summary>
3638
/// <param name="fileContents">The bytes that represent the file contents.</param>
3739
/// <param name="contentType">The Content-Type header of the response.</param>
38-
public FileContentResult([NotNull] byte[] fileContents, string contentType)
40+
public FileContentResult([NotNull] byte[] fileContents, MediaTypeHeaderValue contentType)
3941
: base(contentType)
4042
{
4143
FileContents = fileContents;

src/Microsoft.AspNet.Mvc.Core/ActionResults/FilePathResult.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.AspNet.Mvc.Core;
1212
using Microsoft.Framework.DependencyInjection;
1313
using Microsoft.Framework.Internal;
14+
using Microsoft.Net.Http.Headers;
1415

1516
namespace Microsoft.AspNet.Mvc
1617
{
@@ -27,15 +28,15 @@ public class FilePathResult : FileResult
2728

2829
/// <summary>
2930
/// Creates a new <see cref="FilePathResult"/> instance with
30-
/// the provided <paramref name="fileName"/>
31+
/// the provided <paramref name="fileName"/> and the
32+
/// provided <paramref name="contentType"/>.
3133
/// </summary>
3234
/// <param name="fileName">The path to the file. The path must be an absolute
3335
/// path. Relative and virtual paths are not supported.</param>
3436
/// <param name="contentType">The Content-Type header of the response.</param>
35-
public FilePathResult([NotNull] string fileName)
36-
: base(contentType: null)
37+
public FilePathResult([NotNull] string fileName, string contentType)
38+
: this(fileName, new MediaTypeHeaderValue(contentType))
3739
{
38-
FileName = fileName;
3940
}
4041

4142
/// <summary>
@@ -46,7 +47,7 @@ public FilePathResult([NotNull] string fileName)
4647
/// <param name="fileName">The path to the file. The path must be an absolute
4748
/// path. Relative and virtual paths are not supported.</param>
4849
/// <param name="contentType">The Content-Type header of the response.</param>
49-
public FilePathResult([NotNull] string fileName, string contentType)
50+
public FilePathResult([NotNull] string fileName, MediaTypeHeaderValue contentType)
5051
: base(contentType)
5152
{
5253
FileName = fileName;

src/Microsoft.AspNet.Mvc.Core/ActionResults/FileResult.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,25 @@ public abstract class FileResult : ActionResult
2424
/// the provided <paramref name="contentType"/>.
2525
/// </summary>
2626
/// <param name="contentType">The Content-Type header of the response.</param>
27-
protected FileResult(string contentType)
27+
protected FileResult([NotNull] string contentType)
28+
: this(new MediaTypeHeaderValue(contentType))
29+
{
30+
}
31+
32+
/// <summary>
33+
/// Creates a new <see cref="FileResult"/> instance with
34+
/// the provided <paramref name="Microsoft.Net.Http.Headers.MediaTypeHeaderValue"/>.
35+
/// </summary>
36+
/// <param name="contentType">The Content-Type header of the response.</param>
37+
protected FileResult([NotNull] MediaTypeHeaderValue contentType)
2838
{
2939
ContentType = contentType;
3040
}
3141

3242
/// <summary>
33-
/// Gets or sets the Content-Type header value that will be written to the response.
43+
/// Gets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
3444
/// </summary>
35-
public string ContentType { get; set; }
45+
public MediaTypeHeaderValue ContentType { get; }
3646

3747
/// <summary>
3848
/// Gets the file name that will be used in the Content-Disposition header of the response.
@@ -47,11 +57,7 @@ public string FileDownloadName
4757
public override Task ExecuteResultAsync([NotNull] ActionContext context)
4858
{
4959
var response = context.HttpContext.Response;
50-
51-
if (ContentType != null)
52-
{
53-
response.ContentType = ContentType;
54-
}
60+
response.ContentType = ContentType.ToString();
5561

5662
if (!string.IsNullOrEmpty(FileDownloadName))
5763
{

src/Microsoft.AspNet.Mvc.Core/ActionResults/FileStreamResult.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading.Tasks;
88
using Microsoft.AspNet.Http;
99
using Microsoft.Framework.Internal;
10+
using Microsoft.Net.Http.Headers;
1011

1112
namespace Microsoft.AspNet.Mvc
1213
{
@@ -23,13 +24,14 @@ public class FileStreamResult : FileResult
2324

2425
/// <summary>
2526
/// Creates a new <see cref="FileStreamResult"/> instance with
26-
/// the provided <paramref name="fileStream"/>.
27+
/// the provided <paramref name="fileStream"/> and the
28+
/// provided <paramref name="contentType"/>.
2729
/// </summary>
2830
/// <param name="fileStream">The stream with the file.</param>
29-
public FileStreamResult([NotNull] Stream fileStream)
30-
: base(contentType: null)
31+
/// <param name="contentType">The Content-Type header of the response.</param>
32+
public FileStreamResult([NotNull] Stream fileStream, string contentType)
33+
: this(fileStream, new MediaTypeHeaderValue(contentType))
3134
{
32-
FileStream = fileStream;
3335
}
3436

3537
/// <summary>
@@ -39,7 +41,7 @@ public FileStreamResult([NotNull] Stream fileStream)
3941
/// </summary>
4042
/// <param name="fileStream">The stream with the file.</param>
4143
/// <param name="contentType">The Content-Type header of the response.</param>
42-
public FileStreamResult([NotNull] Stream fileStream, string contentType)
44+
public FileStreamResult([NotNull] Stream fileStream, MediaTypeHeaderValue contentType)
4345
: base(contentType)
4446
{
4547
FileStream = fileStream;

src/Microsoft.AspNet.Mvc.Core/ActionResults/PartialViewResult.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Framework.DependencyInjection;
88
using Microsoft.Framework.Internal;
99
using Microsoft.Framework.Logging;
10+
using Microsoft.Net.Http.Headers;
1011

1112
namespace Microsoft.AspNet.Mvc
1213
{
@@ -45,6 +46,11 @@ public class PartialViewResult : ActionResult
4546
/// <c>ActionContext.HttpContext.RequestServices</c> is used.</remarks>
4647
public IViewEngine ViewEngine { get; set; }
4748

49+
/// <summary>
50+
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
51+
/// </summary>
52+
public MediaTypeHeaderValue ContentType { get; set; }
53+
4854
/// <inheritdoc />
4955
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
5056
{
@@ -74,7 +80,7 @@ public override async Task ExecuteResultAsync([NotNull] ActionContext context)
7480

7581
using (view as IDisposable)
7682
{
77-
await ViewExecutor.ExecuteAsync(view, context, ViewData, TempData, contentType: null);
83+
await ViewExecutor.ExecuteAsync(view, context, ViewData, TempData, ContentType);
7884
}
7985
}
8086
}

0 commit comments

Comments
 (0)