diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Formatters/InputFormatter.cs b/src/Microsoft.AspNetCore.Mvc.Core/Formatters/InputFormatter.cs
index 8b9c00115f..c6fe0e94a1 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Formatters/InputFormatter.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Formatters/InputFormatter.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.AspNetCore.Mvc.Core;
namespace Microsoft.AspNetCore.Mvc.Formatters
{
@@ -43,6 +44,15 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
///
public virtual bool CanRead(InputFormatterContext context)
{
+ if (SupportedMediaTypes.Count == 0)
+ {
+ var message = Resources.FormatFormatter_NoMediaTypes(
+ GetType().FullName,
+ nameof(SupportedMediaTypes));
+
+ throw new InvalidOperationException(message);
+ }
+
if (!CanReadType(context.ModelType))
{
return false;
@@ -111,6 +121,15 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
///
public virtual IReadOnlyList GetSupportedContentTypes(string contentType, Type objectType)
{
+ if (SupportedMediaTypes.Count == 0)
+ {
+ var message = Resources.FormatFormatter_NoMediaTypes(
+ GetType().FullName,
+ nameof(SupportedMediaTypes));
+
+ throw new InvalidOperationException(message);
+ }
+
if (!CanReadType(objectType))
{
return null;
@@ -119,7 +138,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
if (contentType == null)
{
// If contentType is null, then any type we support is valid.
- return SupportedMediaTypes.Count > 0 ? SupportedMediaTypes : null;
+ return SupportedMediaTypes;
}
else
{
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Formatters/OutputFormatter.cs b/src/Microsoft.AspNetCore.Mvc.Core/Formatters/OutputFormatter.cs
index 314fadbfe9..9ba3d68b3e 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Formatters/OutputFormatter.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Formatters/OutputFormatter.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Mvc.Formatters
@@ -14,19 +15,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
///
public abstract class OutputFormatter : IOutputFormatter, IApiResponseFormatMetadataProvider
{
- ///
- /// Initializes a new instance of the class.
- ///
- protected OutputFormatter()
- {
- SupportedMediaTypes = new MediaTypeCollection();
- }
-
///
/// Gets the mutable collection of media type elements supported by
/// this .
///
- public MediaTypeCollection SupportedMediaTypes { get; }
+ public MediaTypeCollection SupportedMediaTypes { get; } = new MediaTypeCollection();
///
/// Returns a value indicating whether or not the given type can be written by this serializer.
@@ -43,6 +36,15 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
string contentType,
Type objectType)
{
+ if (SupportedMediaTypes.Count == 0)
+ {
+ var message = Resources.FormatFormatter_NoMediaTypes(
+ GetType().FullName,
+ nameof(SupportedMediaTypes));
+
+ throw new InvalidOperationException(message);
+ }
+
if (!CanWriteType(objectType))
{
return null;
@@ -51,7 +53,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
if (contentType == null)
{
// If contentType is null, then any type we support is valid.
- return SupportedMediaTypes.Count > 0 ? SupportedMediaTypes : null;
+ return SupportedMediaTypes;
}
else
{
@@ -87,6 +89,15 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
throw new ArgumentNullException(nameof(context));
}
+ if (SupportedMediaTypes.Count == 0)
+ {
+ var message = Resources.FormatFormatter_NoMediaTypes(
+ GetType().FullName,
+ nameof(SupportedMediaTypes));
+
+ throw new InvalidOperationException(message);
+ }
+
if (!CanWriteType(context.ObjectType))
{
return false;
@@ -96,15 +107,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
// If the desired content type is set to null, then the current formatter can write anything
// it wants.
- if (SupportedMediaTypes.Count > 0)
- {
- context.ContentType = new StringSegment(SupportedMediaTypes[0]);
- return true;
- }
- else
- {
- return false;
- }
+ context.ContentType = new StringSegment(SupportedMediaTypes[0]);
+ return true;
}
else
{
@@ -160,4 +164,4 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
/// A task which can write the response body.
public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);
}
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
index db8b79a02b..55a474f187 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
@@ -1146,6 +1146,22 @@ namespace Microsoft.AspNetCore.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("TextOutpurFormatter_WriteResponseBodyAsynNotSupported"), p0, p1, p2);
}
+ ///
+ /// No media types found in '{0}.{1}'. Add at least one media type to the list of supported media types.
+ ///
+ internal static string Formatter_NoMediaTypes
+ {
+ get { return GetString("Formatter_NoMediaTypes"); }
+ }
+
+ ///
+ /// No media types found in '{0}.{1}'. Add at least one media type to the list of supported media types.
+ ///
+ internal static string FormatFormatter_NoMediaTypes(object p0, object p1)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("Formatter_NoMediaTypes"), p0, p1);
+ }
+
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
index 84d1befc53..04dc1391b1 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
@@ -1,17 +1,17 @@
-
@@ -340,4 +340,7 @@
'{0}' is not supported by '{1}'. Use '{2}' instead.
+
+ No media types found in '{0}.{1}'. Add at least one media type to the list of supported media types.
+
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/InputFormatterTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/InputFormatterTest.cs
index 6ddb2d3838..eae5c6eecd 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/InputFormatterTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/InputFormatterTest.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Internal;
@@ -382,6 +383,41 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Collection(results, c => Assert.Equal("text/xml", c));
}
+ [Fact]
+ public void CanRead_ThrowsInvalidOperationException_IfMediaTypesListIsEmpty()
+ {
+ // Arrange
+ var formatter = new BadConfigurationFormatter();
+ var context = new InputFormatterContext(
+ new DefaultHttpContext(),
+ "",
+ new ModelStateDictionary(),
+ new EmptyModelMetadataProvider().GetMetadataForType(typeof(object)),
+ (s, e) => new StreamReader(s, e));
+
+ // Act & Assert
+ Assert.Throws(() => formatter.CanRead(context));
+ }
+
+ [Fact]
+ public void GetSupportedContentTypes_ThrowsInvalidOperationException_IfMediaTypesListIsEmpty()
+ {
+ // Arrange
+ var formatter = new BadConfigurationFormatter();
+
+ // Act & Assert
+ Assert.Throws(
+ () => formatter.GetSupportedContentTypes("application/json", typeof(object)));
+ }
+
+ private class BadConfigurationFormatter : InputFormatter
+ {
+ public override Task ReadRequestBodyAsync(InputFormatterContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
private class TestFormatter : InputFormatter
{
public IList SupportedTypes { get; } = new List();
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/OutputFormatterTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
index 6476947fd5..20407b07fe 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@@ -138,24 +139,6 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Null(contentTypes);
}
- [Fact]
- public void GetSupportedContentTypes_ReturnsAllContentTypes_ReturnsNullWithNoSupportedContentTypes()
- {
- // Arrange
- var formatter = new TestOutputFormatter();
-
- // Intentionally empty
- formatter.SupportedMediaTypes.Clear();
-
- // Act
- var contentTypes = formatter.GetSupportedContentTypes(
- contentType: null,
- objectType: typeof(int));
-
- // Assert
- Assert.Null(contentTypes);
- }
-
private class TypeSpecificFormatter : OutputFormatter
{
public List SupportedTypes { get; } = new List();
@@ -171,6 +154,35 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
}
+ [Fact]
+ public void CanWrite_ThrowsInvalidOperationException_IfMediaTypesListIsEmpty()
+ {
+ // Arrange
+ var formatter = new TestOutputFormatter();
+ formatter.SupportedMediaTypes.Clear();
+
+ var context = new OutputFormatterWriteContext(
+ new DefaultHttpContext(),
+ (s, e) => new StreamWriter(s, e),
+ typeof(object),
+ new object());
+
+ // Act & Assert
+ Assert.Throws(() => formatter.CanWriteResult(context));
+ }
+
+ [Fact]
+ public void GetSupportedContentTypes_ThrowsInvalidOperationException_IfMediaTypesListIsEmpty()
+ {
+ // Arrange
+ var formatter = new TestOutputFormatter();
+ formatter.SupportedMediaTypes.Clear();
+
+ // Act & Assert
+ Assert.Throws(
+ () => formatter.GetSupportedContentTypes("application/json", typeof(object)));
+ }
+
private class TestOutputFormatter : OutputFormatter
{
public TestOutputFormatter()