This change removes the validation that forces an OutputFormatter to set
an encoding, so that you can use the OutputFormatter base class for
non-text.

The check that we had would pretty much only be hit when you
didn't have any SupportedEncodings. If you have anything in
SupportedEncodings, then one of them will be picked as a default. So
removing the check is to do, because for a text-based formatter you'd
never run into this issue in the first place.
This commit is contained in:
Ryan Nowak 2015-07-09 13:42:07 -07:00
parent 8cb2aae4f5
commit 35ee0e3a49
4 changed files with 37 additions and 42 deletions

View File

@ -182,19 +182,26 @@ namespace Microsoft.AspNet.Mvc
// Copy the media type as we don't want it to affect the next request
selectedMediaType = selectedMediaType.Copy();
// Not text-based media types will use an encoding/charset - binary formats just ignore it. We want to
// make this class work with media types that use encodings, and those that don't.
//
// The default implementation of SelectCharacterEncoding will read from the list of SupportedEncodings
// and will always choose a default encoding if any are supported. So, the only cases where the
// selectedEncoding can be null are:
//
// 1). No supported encodings - we assume this is a non-text format
// 2). Custom implementation of SelectCharacterEncoding - trust the user and give them what they want.
var selectedEncoding = SelectCharacterEncoding(context);
if (selectedEncoding == null)
if (selectedEncoding != null)
{
// No supported encoding was found so there is no way for us to start writing.
throw new InvalidOperationException(Resources.FormatOutputFormatterNoEncoding(GetType().FullName));
context.SelectedEncoding = selectedEncoding;
// Override the content type value even if one already existed.
selectedMediaType.Charset = selectedEncoding.WebName;
}
context.SelectedEncoding = selectedEncoding;
// Override the content type value even if one already existed.
selectedMediaType.Charset = selectedEncoding.WebName;
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
var response = context.HttpContext.Response;
response.ContentType = selectedMediaType.ToString();
}

View File

@ -362,22 +362,6 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("TypeMustDeriveFromType"), p0, p1);
}
/// <summary>
/// No encoding found for output formatter '{0}'. There must be at least one supported encoding registered in order for the output formatter to write content.
/// </summary>
internal static string OutputFormatterNoEncoding
{
get { return GetString("OutputFormatterNoEncoding"); }
}
/// <summary>
/// No encoding found for output formatter '{0}'. There must be at least one supported encoding registered in order for the output formatter to write content.
/// </summary>
internal static string FormatOutputFormatterNoEncoding(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("OutputFormatterNoEncoding"), p0);
}
/// <summary>
/// No encoding found for input formatter '{0}'. There must be at least one supported encoding registered in order for the formatter to read content.
/// </summary>

View File

@ -183,9 +183,6 @@
<data name="TypeMustDeriveFromType" xml:space="preserve">
<value>The type '{0}' must derive from '{1}'.</value>
</data>
<data name="OutputFormatterNoEncoding" xml:space="preserve">
<value>No encoding found for output formatter '{0}'. There must be at least one supported encoding registered in order for the output formatter to write content.</value>
</data>
<data name="InputFormatterNoEncoding" xml:space="preserve">
<value>No encoding found for input formatter '{0}'. There must be at least one supported encoding registered in order for the formatter to read content.</value>
</data>

View File

@ -76,24 +76,31 @@ namespace Microsoft.AspNet.Mvc.Test
}
[Fact]
public void WriteResponseContentHeaders_FormatterWithNoEncoding_Throws()
public void WriteResponseContentHeaders_NoSupportedEncodings_NoEncodingIsSet()
{
// Arrange
var testFormatter = new TestOutputFormatter();
var testContentType = MediaTypeHeaderValue.Parse("text/invalid");
var formatterContext = new OutputFormatterContext();
var mockHttpContext = new Mock<HttpContext>();
var httpRequest = new DefaultHttpContext().Request;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
formatterContext.HttpContext = mockHttpContext.Object;
var formatter = new TestOutputFormatter();
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(
() => testFormatter.WriteResponseHeaders(formatterContext));
Assert.Equal("No encoding found for output formatter " +
"'Microsoft.AspNet.Mvc.Test.OutputFormatterTests+TestOutputFormatter'." +
" There must be at least one supported encoding registered in order for the" +
" output formatter to write content.", ex.Message);
var testContentType = MediaTypeHeaderValue.Parse("text/json");
formatter.SupportedEncodings.Clear();
formatter.SupportedMediaTypes.Clear();
formatter.SupportedMediaTypes.Add(testContentType);
var formatterContext = new OutputFormatterContext()
{
HttpContext = new DefaultHttpContext(),
};
// Act
formatter.WriteResponseHeaders(formatterContext);
// Assert
Assert.Null(formatterContext.SelectedEncoding);
Assert.Equal(testContentType, formatterContext.SelectedContentType);
// If we had set an encoding, it would be part of the content type header
Assert.Equal(testContentType, formatterContext.HttpContext.Response.GetTypedHeaders().ContentType);
}
[Fact]