[Fixes #3433] Invalid media type 'text/plain; charset=utf-8'
This commit is contained in:
parent
4bcf236450
commit
31e42ee312
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"commands": {
|
"commands": {
|
||||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
"web": "Microsoft.AspNet.Server.Kestrel",
|
||||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||||
},
|
},
|
||||||
"compilationOptions": {
|
"compilationOptions": {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <param name="fileContents">The bytes that represent the file contents.</param>
|
/// <param name="fileContents">The bytes that represent the file contents.</param>
|
||||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||||
public FileContentResult(byte[] fileContents, string contentType)
|
public FileContentResult(byte[] fileContents, string contentType)
|
||||||
: this(fileContents, new MediaTypeHeaderValue(contentType))
|
: this(fileContents, MediaTypeHeaderValue.Parse(contentType))
|
||||||
{
|
{
|
||||||
if (fileContents == null)
|
if (fileContents == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
private string _fileDownloadName;
|
private string _fileDownloadName;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new <see cref="FileResult"/> instance with
|
|
||||||
/// the provided <paramref name="contentType"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
|
||||||
protected FileResult(string contentType)
|
|
||||||
: this(new MediaTypeHeaderValue(contentType))
|
|
||||||
{
|
|
||||||
if (contentType == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(contentType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="FileResult"/> instance with
|
/// Creates a new <see cref="FileResult"/> instance with
|
||||||
/// the provided <paramref name="contentType"/>.
|
/// the provided <paramref name="contentType"/>.
|
||||||
|
|
@ -87,7 +73,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
contentDisposition.SetHttpFileName(FileDownloadName);
|
contentDisposition.SetHttpFileName(FileDownloadName);
|
||||||
context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
|
context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.FileResultExecuting(FileDownloadName);
|
logger.FileResultExecuting(FileDownloadName);
|
||||||
return WriteFileAsync(response);
|
return WriteFileAsync(response);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <param name="fileStream">The stream with the file.</param>
|
/// <param name="fileStream">The stream with the file.</param>
|
||||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||||
public FileStreamResult(Stream fileStream, string contentType)
|
public FileStreamResult(Stream fileStream, string contentType)
|
||||||
: this(fileStream, new MediaTypeHeaderValue(contentType))
|
: this(fileStream, MediaTypeHeaderValue.Parse(contentType))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <param name="fileName">The path to the file. The path must be an absolute path.</param>
|
/// <param name="fileName">The path to the file. The path must be an absolute path.</param>
|
||||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||||
public PhysicalFileResult(string fileName, string contentType)
|
public PhysicalFileResult(string fileName, string contentType)
|
||||||
: this(fileName, new MediaTypeHeaderValue(contentType))
|
: this(fileName, MediaTypeHeaderValue.Parse(contentType))
|
||||||
{
|
{
|
||||||
if (fileName == null)
|
if (fileName == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <param name="fileName">The path to the file. The path must be relative/virtual.</param>
|
/// <param name="fileName">The path to the file. The path must be relative/virtual.</param>
|
||||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||||
public VirtualFileResult(string fileName, string contentType)
|
public VirtualFileResult(string fileName, string contentType)
|
||||||
: this(fileName, new MediaTypeHeaderValue(contentType))
|
: this(fileName, MediaTypeHeaderValue.Parse(contentType))
|
||||||
{
|
{
|
||||||
if (fileName == null)
|
if (fileName == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -467,7 +467,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ContentResult Content(string content, string contentType)
|
public virtual ContentResult Content(string content, string contentType)
|
||||||
{
|
{
|
||||||
return Content(content, contentType, contentEncoding: null);
|
return Content(content, MediaTypeHeaderValue.Parse(contentType));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -478,10 +478,16 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <param name="contentType">The content type (MIME type).</param>
|
/// <param name="contentType">The content type (MIME type).</param>
|
||||||
/// <param name="contentEncoding">The content encoding.</param>
|
/// <param name="contentEncoding">The content encoding.</param>
|
||||||
/// <returns>The created <see cref="ContentResult"/> object for the response.</returns>
|
/// <returns>The created <see cref="ContentResult"/> object for the response.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If encoding is provided by both the 'charset' and the <paramref name="contentEncoding"/> parameters, then
|
||||||
|
/// the <paramref name="contentEncoding"/> parameter is chosen as the final encoding.
|
||||||
|
/// </remarks>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ContentResult Content(string content, string contentType, Encoding contentEncoding)
|
public virtual ContentResult Content(string content, string contentType, Encoding contentEncoding)
|
||||||
{
|
{
|
||||||
return Content(content, new MediaTypeHeaderValue(contentType) { Encoding = contentEncoding });
|
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
mediaTypeHeaderValue.Encoding = contentEncoding ?? mediaTypeHeaderValue.Encoding;
|
||||||
|
return Content(content, mediaTypeHeaderValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -639,7 +645,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a <see cref="LocalRedirectResult"/> object with <see cref="LocalRedirectResult.Permanent"/>
|
/// Creates a <see cref="LocalRedirectResult"/> object with <see cref="LocalRedirectResult.Permanent"/>
|
||||||
/// set to true using the specified <paramref name="localUrl"/>.
|
/// set to true using the specified <paramref name="localUrl"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="localUrl">The local URL to redirect to.</param>
|
/// <param name="localUrl">The local URL to redirect to.</param>
|
||||||
|
|
@ -1756,7 +1762,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(model));
|
throw new ArgumentNullException(nameof(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
var modelName = prefix ?? string.Empty;
|
var modelName = prefix ?? string.Empty;
|
||||||
|
|
||||||
// Clear ModelStateDictionary entries for the model so that it will be re-validated.
|
// Clear ModelStateDictionary entries for the model so that it will be re-validated.
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,22 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Assert.Same(fileContents, result.FileContents);
|
Assert.Same(fileContents, result.FileContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_SetsContentTypeAndParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var fileContents = new byte[0];
|
||||||
|
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
|
||||||
|
var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new FileContentResult(fileContents, contentType);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(fileContents, result.FileContents);
|
||||||
|
Assert.Equal(expectedMediaType, result.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteFileAsync_CopiesBuffer_ToOutputStream()
|
public async Task WriteFileAsync_CopiesBuffer_ToOutputStream()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -275,12 +275,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public bool WasWriteFileCalled;
|
public bool WasWriteFileCalled;
|
||||||
|
|
||||||
public EmptyFileResult()
|
public EmptyFileResult()
|
||||||
: this(MediaTypeNames.Application.Octet)
|
: base(MediaTypeHeaderValue.Parse(MediaTypeNames.Application.Octet))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmptyFileResult(string contentType)
|
public EmptyFileResult(string contentType)
|
||||||
: base(contentType)
|
: base(MediaTypeHeaderValue.Parse(contentType))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,22 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Assert.Equal(stream, result.FileStream);
|
Assert.Equal(stream, result.FileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_SetsContentTypeAndParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var stream = Stream.Null;
|
||||||
|
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
|
||||||
|
var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new FileStreamResult(stream, contentType);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(stream, result.FileStream);
|
||||||
|
Assert.Equal(expectedMediaType, result.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteFileAsync_WritesResponse_InChunksOfFourKilobytes()
|
public async Task WriteFileAsync_WritesResponse_InChunksOfFourKilobytes()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,22 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Assert.Equal(path, result.FileName);
|
Assert.Equal(path, result.FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_SetsContentTypeAndParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var path = Path.GetFullPath("helllo.txt");
|
||||||
|
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
|
||||||
|
var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new PhysicalFileResult(path, contentType);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(path, result.FileName);
|
||||||
|
Assert.Equal(expectedMediaType, result.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ExecuteResultAsync_FallsbackToStreamCopy_IfNoIHttpSendFilePresent()
|
public async Task ExecuteResultAsync_FallsbackToStreamCopy_IfNoIHttpSendFilePresent()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,22 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Assert.Equal(path, result.FileName);
|
Assert.Equal(path, result.FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_SetsContentTypeAndParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var path = Path.GetFullPath("helllo.txt");
|
||||||
|
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
|
||||||
|
var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new VirtualFileResult(path, contentType);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(path, result.FileName);
|
||||||
|
Assert.Equal(expectedMediaType, result.ContentType);
|
||||||
|
|
||||||
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ExecuteResultAsync_FallsBackToWebRootFileProvider_IfNoFileProviderIsPresent()
|
public async Task ExecuteResultAsync_FallsBackToWebRootFileProvider_IfNoFileProviderIsPresent()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.AspNet.Mvc.ViewFeatures;
|
using Microsoft.AspNet.Mvc.ViewFeatures;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.AspNet.Testing;
|
using Microsoft.AspNet.Testing;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -1107,6 +1108,66 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
Assert.Equal("text/plain; charset=utf-8", actualContentResult.ContentType.ToString());
|
Assert.Equal("text/plain; charset=utf-8", actualContentResult.ContentType.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Controller_Content_NoContentType_DefaultEncodingIsUsed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contentController = new ContentController();
|
||||||
|
var expected = MediaTypeHeaderValue.Parse("text/plain; charset=utf-8");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var contentResult = (ContentResult)contentController.Content_WithNoEncoding();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// The default content type of ContentResult is used when the result is executed.
|
||||||
|
Assert.Null(contentResult.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Controller_Content_InvalidCharset_DefaultEncodingIsUsed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contentController = new ContentController();
|
||||||
|
var contentType = "text/xml; charset=invalid; p1=p1-value";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var contentResult = (ContentResult)contentController.Content_WithInvalidCharset();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(contentResult.ContentType);
|
||||||
|
Assert.Equal(contentType, contentResult.ContentType.ToString());
|
||||||
|
// The default encoding of ContentResult is used when this result is executed.
|
||||||
|
Assert.Null(contentResult.ContentType.Encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Controller_Content_CharsetAndEncodingProvided_EncodingIsUsed()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contentController = new ContentController();
|
||||||
|
var contentType = MediaTypeHeaderValue.Parse("text/xml; charset=us-ascii; p1=p1-value");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var contentResult = (ContentResult)contentController.Content_WithEncodingInCharset_AndEncodingParameter();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(contentType, contentResult.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Controller_Content_CharsetInContentType_IsUsedForEncoding()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contentController = new ContentController();
|
||||||
|
var contentType = MediaTypeHeaderValue.Parse("text/xml; charset=us-ascii; p1=p1-value");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var contentResult = (ContentResult)contentController.Content_WithEncodingInCharset();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(contentType, contentResult.ContentType);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Controller_Json_WithParameterValue_SetsResultData()
|
public void Controller_Json_WithParameterValue_SetsResultData()
|
||||||
{
|
{
|
||||||
|
|
@ -1883,6 +1944,29 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ContentController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Content_WithNoEncoding()
|
||||||
|
{
|
||||||
|
return Content("Hello!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult Content_WithEncodingInCharset()
|
||||||
|
{
|
||||||
|
return Content("Hello!!", "text/xml; charset=us-ascii; p1=p1-value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult Content_WithInvalidCharset()
|
||||||
|
{
|
||||||
|
return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult Content_WithEncodingInCharset_AndEncodingParameter()
|
||||||
|
{
|
||||||
|
return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value", Encoding.ASCII);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue