diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ObjectResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ObjectResult.cs index 67d9273b58..69fd10e367 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ObjectResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ObjectResult.cs @@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Mvc { DeclaredType = DeclaredType, ActionContext = context, - Object = Value, + Object = Value, }; var selectedFormatter = SelectFormatter(formatterContext, formatters); @@ -89,12 +89,15 @@ namespace Microsoft.AspNet.Mvc // This would be the case when no formatter could write the type base on the // accept headers and the request content type. Fallback on type based match. - if(selectedFormatter == null) + if (selectedFormatter == null) { foreach (var formatter in formatters) { - if (formatter.CanWriteResult(formatterContext, - formatter.SupportedMediaTypes?.FirstOrDefault())) + var supportedContentTypes = formatter.GetSupportedContentTypes( + GetObjectType(formatterContext), + contentType: null); + + if (formatter.CanWriteResult(formatterContext, supportedContentTypes?.FirstOrDefault())) { return formatter; } @@ -175,7 +178,7 @@ namespace Microsoft.AspNet.Mvc IEnumerable acceptableContentTypes) { var selectedFormatter = formatters.FirstOrDefault( - formatter => + formatter => acceptableContentTypes .Any(contentType => formatter.CanWriteResult(formatterContext, contentType))); @@ -215,5 +218,18 @@ namespace Microsoft.AspNet.Mvc return formatters; } + + private Type GetObjectType([NotNull] OutputFormatterContext context) + { + if (context.DeclaredType == null || context.DeclaredType == typeof(object)) + { + if (context.Object != null) + { + return context.Object.GetType(); + } + } + + return context.DeclaredType; + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/IOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/IOutputFormatter.cs index 4651dbe735..5a43ecd975 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Formatters/IOutputFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/IOutputFormatter.cs @@ -19,17 +19,13 @@ namespace Microsoft.AspNet.Mvc public interface IOutputFormatter { /// - /// Gets the mutable collection of character encodings supported by - /// this . The encodings are - /// used when writing the data. + /// Gets a filtered list of content types which are supported by this formatter + /// for the and . /// - IList SupportedEncodings { get; } - - /// - /// Gets the mutable collection of elements supported by - /// this . - /// - IList SupportedMediaTypes { get; } + /// Type for which the supported content types are desired. + /// Content type for which the supported content types are desired. + /// Content types which can are supported by this formatter. + IReadOnlyList GetSupportedContentTypes(Type dataType, MediaTypeHeaderValue contentType); /// /// Determines whether this can serialize diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/NoContentFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/NoContentFormatter.cs index ae65b159c5..9ba33c9d44 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Formatters/NoContentFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/NoContentFormatter.cs @@ -14,10 +14,6 @@ namespace Microsoft.AspNet.Mvc /// public class NoContentFormatter : IOutputFormatter { - public IList SupportedEncodings { get; private set; } - - public IList SupportedMediaTypes { get; private set; } - public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { // ignore the contentType and just look at the content. @@ -25,6 +21,11 @@ namespace Microsoft.AspNet.Mvc return context.Object == null; } + public IReadOnlyList GetSupportedContentTypes(Type dataType, MediaTypeHeaderValue contentType) + { + return null; + } + public Task WriteAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs index 1811c3a495..438f21e099 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs @@ -26,12 +26,36 @@ namespace Microsoft.AspNet.Mvc SupportedMediaTypes = new List(); } - /// + /// + /// Gets the mutable collection of character encodings supported by + /// this . The encodings are + /// used when writing the data. + /// public IList SupportedEncodings { get; private set; } - /// + /// + /// Gets the mutable collection of elements supported by + /// this . + /// public IList SupportedMediaTypes { get; private set; } + /// + public virtual IReadOnlyList GetSupportedContentTypes(Type dataType, MediaTypeHeaderValue contentType) + { + var mediaTypes = new List(); + + if (contentType == null) + { + mediaTypes.AddRange(SupportedMediaTypes); + } + else + { + mediaTypes.Add(SupportedMediaTypes.FirstOrDefault(mt => mt.IsSubsetOf(contentType))); + } + + return mediaTypes; + } + /// /// Determines the best amongst the supported encodings /// for reading or writing an HTTP entity body based on the provided . diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/ObjectResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/ObjectResultTests.cs index 2551fb93e3..bfee0fccfd 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/ObjectResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/ObjectResultTests.cs @@ -545,27 +545,17 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults public class CannotWriteFormatter : IOutputFormatter { - public IList SupportedEncodings - { - get - { - return null; - } - } - - public IList SupportedMediaTypes - { - get - { - return null; - } - } - public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { return false; } + public IReadOnlyList GetSupportedContentTypes(Type dataType, + MediaTypeHeaderValue contentType) + { + return null; + } + public virtual Task WriteAsync(OutputFormatterContext context) { throw new NotImplementedException(); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs index 6e6e2a68b8..28931ecaa6 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs @@ -113,27 +113,17 @@ namespace Microsoft.AspNet.Mvc { public Encoding Encoding { get; set; } - public IList SupportedEncodings - { - get - { - return null; - } - } - - public IList SupportedMediaTypes - { - get - { - return null; - } - } - public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { return true; } + public IReadOnlyList GetSupportedContentTypes(Type dataType, + MediaTypeHeaderValue contentType) + { + return null; + } + public async Task WriteAsync(OutputFormatterContext context) { // Override using the selected encoding. diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/OutputFormatterDescriptorTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/OutputFormatterDescriptorTest.cs index f426ab80df..78cff7970d 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/OutputFormatterDescriptorTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/OutputFormatterDescriptorTest.cs @@ -57,27 +57,17 @@ namespace Microsoft.AspNet.Mvc.Core private class TestOutputFormatter : IOutputFormatter { - public IList SupportedEncodings - { - get - { - return null; - } - } - - public IList SupportedMediaTypes - { - get - { - return null; - } - } - public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { throw new NotImplementedException(); } + public IReadOnlyList GetSupportedContentTypes(Type dataType, + MediaTypeHeaderValue contentType) + { + return null; + } + public Task WriteAsync(OutputFormatterContext context) { throw new NotImplementedException(); diff --git a/test/WebSites/ConnegWebSite/Controllers/FallbackOnTypeBasedMatchController.cs b/test/WebSites/ConnegWebSite/Controllers/FallbackOnTypeBasedMatchController.cs index 330682001c..b200d7de49 100644 --- a/test/WebSites/ConnegWebSite/Controllers/FallbackOnTypeBasedMatchController.cs +++ b/test/WebSites/ConnegWebSite/Controllers/FallbackOnTypeBasedMatchController.cs @@ -68,28 +68,17 @@ namespace ConnegWebsite public class StopIfNoMatchOutputFormatter : IOutputFormatter { - public IList SupportedEncodings - { - get - { - return null; - } - } - - public IList SupportedMediaTypes - { - get - { - return null; - } - } - // Select if no Registered content type. public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { return contentType == null; } + public IReadOnlyList GetSupportedContentTypes(Type dataType, MediaTypeHeaderValue contentType) + { + return null; + } + public Task WriteAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response;