diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs
index 4ed6f1e06d..2f598152f0 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs
@@ -9,104 +9,124 @@
namespace Microsoft.AspNet.Mvc
{
+ ///
+ /// An action result which formats the given object as JSON.
+ ///
public class JsonResult : ActionResult
{
- private static readonly IList _defaultSupportedContentTypes =
- new List()
- {
- MediaTypeHeaderValue.Parse("application/json"),
- MediaTypeHeaderValue.Parse("text/json"),
- };
- private IOutputFormatter _defaultFormatter;
-
- private ObjectResult _objectResult;
-
- public JsonResult(object data) :
- this(data, null)
+ ///
+ /// The list of content-types used for formatting when is null or empty.
+ ///
+ public static readonly IReadOnlyList DefaultContentTypes = new MediaTypeHeaderValue[]
{
- }
+ MediaTypeHeaderValue.Parse("application/json"),
+ MediaTypeHeaderValue.Parse("text/json"),
+ };
///
- /// Creates an instance of class.
+ /// Creates a new with the given .
///
- ///
- /// If no matching formatter is found,
- /// the response is written to using defaultFormatter.
- ///
- /// The default formatter must be able to handle either application/json
- /// or text/json.
- ///
- public JsonResult(object data, IOutputFormatter defaultFormatter)
+ /// The value to format as JSON.
+ public JsonResult(object value)
+ : this(value, formatter: null)
{
- _defaultFormatter = defaultFormatter;
- _objectResult = new ObjectResult(data);
}
- public object Value
+ ///
+ /// Creates a new with the given .
+ ///
+ /// The value to format as JSON.
+ /// The formatter to use, or null to choose a formatter dynamically.
+ public JsonResult(object value, IOutputFormatter formatter)
{
- get
- {
- return _objectResult.Value;
- }
- set
- {
- _objectResult.Value = value;
- }
- }
+ Value = value;
+ Formatter = formatter;
- public IList ContentTypes
- {
- get
- {
- return _objectResult.ContentTypes;
- }
- set
- {
- _objectResult.ContentTypes = value;
- }
+ ContentTypes = new List();
}
+ ///
+ /// Gets or sets the list of supported Content-Types.
+ ///
+ public IList ContentTypes { get; set; }
+
+ ///
+ /// Gets or sets the formatter.
+ ///
+ public IOutputFormatter Formatter { get; set; }
+
+ ///
+ /// Gets or sets the value to be formatted.
+ ///
+ public object Value { get; set; }
+
+ ///
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
{
+ var objectResult = new ObjectResult(Value);
+
// Set the content type explicitly to application/json and text/json.
// if the user has not already set it.
if (ContentTypes == null || ContentTypes.Count == 0)
{
- ContentTypes = _defaultSupportedContentTypes;
+ foreach (var contentType in DefaultContentTypes)
+ {
+ objectResult.ContentTypes.Add(contentType);
+ }
+ }
+ else
+ {
+ objectResult.ContentTypes = ContentTypes;
}
var formatterContext = new OutputFormatterContext()
{
- DeclaredType = _objectResult.DeclaredType,
ActionContext = context,
+ DeclaredType = objectResult.DeclaredType,
Object = Value,
};
- // Need to call this instead of directly calling _objectResult.ExecuteResultAsync
- // as that sets the status to 406 if a formatter is not found.
- // this can be cleaned up after https://github.com/aspnet/Mvc/issues/941 gets resolved.
- var formatter = SelectFormatter(formatterContext);
+ var formatter = SelectFormatter(objectResult, formatterContext);
await formatter.WriteAsync(formatterContext);
}
- private IOutputFormatter SelectFormatter(OutputFormatterContext formatterContext)
+ private IOutputFormatter SelectFormatter(ObjectResult objectResult, OutputFormatterContext formatterContext)
{
- var defaultFormatters = formatterContext.ActionContext
- .HttpContext
- .RequestServices
- .GetRequiredService()
- .OutputFormatters;
-
- var formatter = _objectResult.SelectFormatter(formatterContext, defaultFormatters);
- if (formatter == null)
+ if (Formatter == null)
{
- formatter = _defaultFormatter ?? formatterContext.ActionContext
- .HttpContext
- .RequestServices
- .GetRequiredService();
- }
+ // If no formatter was provided, then run Conneg with the formatters configured in options.
+ var formatters = formatterContext
+ .ActionContext
+ .HttpContext
+ .RequestServices
+ .GetRequiredService()
+ .OutputFormatters
+ .OfType()
+ .ToArray();
+
+ var formatter = objectResult.SelectFormatter(formatterContext, formatters);
+ if (formatter == null)
+ {
+ // If the available user-configured formatters can't write this type, then fall back to the
+ // 'global' one.
+ formatter = formatterContext
+ .ActionContext
+ .HttpContext
+ .RequestServices
+ .GetRequiredService();
- return formatter;
+ // Run SelectFormatter again to try to choose a content type that this formatter can do.
+ objectResult.SelectFormatter(formatterContext, new[] { formatter });
+ }
+
+ return formatter;
+ }
+ else
+ {
+ // Run SelectFormatter to try to choose a content type that this formatter can do.
+ objectResult.SelectFormatter(formatterContext, new[] { Formatter });
+ return Formatter;
+ }
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/IJsonOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/IJsonOutputFormatter.cs
new file mode 100644
index 0000000000..db86820470
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/IJsonOutputFormatter.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace Microsoft.AspNet.Mvc
+{
+ ///
+ /// An output formatter that specializes in writing JSON content.
+ ///
+ ///
+ /// The class filter the collection of
+ /// and use only those which implement
+ /// .
+ ///
+ /// To create a custom formatter that can be used by , derive from
+ /// or implement .
+ ///
+ public interface IJsonOutputFormatter : IOutputFormatter
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/JsonOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/JsonOutputFormatter.cs
index 1a017f92d5..55dc17c7e2 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/JsonOutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/JsonOutputFormatter.cs
@@ -9,7 +9,7 @@
namespace Microsoft.AspNet.Mvc
{
- public class JsonOutputFormatter : OutputFormatter
+ public class JsonOutputFormatter : OutputFormatter, IJsonOutputFormatter
{
private JsonSerializerSettings _serializerSettings;
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs
index d09c1c12e5..670ce70b67 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/JsonResultTest.cs
@@ -9,11 +9,11 @@
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
+using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Moq;
using Xunit;
-
namespace Microsoft.AspNet.Mvc
{
public class JsonResultTest
@@ -22,114 +22,192 @@ private static readonly byte[] _abcdUTF8Bytes
= new byte[] { 123, 34, 102, 111, 111, 34, 58, 34, 97, 98, 99, 100, 34, 125 };
[Fact]
- public async Task ExecuteResult_GeneratesResultsWithoutBOMByDefault()
+ public async Task ExecuteResultAsync_OptionsFormatter_WithoutBOM()
{
// Arrange
var expected = _abcdUTF8Bytes;
- var memoryStream = new MemoryStream();
- var response = new Mock();
- response.SetupGet(r => r.Body)
- .Returns(memoryStream);
- var context = GetHttpContext(response.Object);
- var actionContext = new ActionContext(context,
- new RouteData(),
- new ActionDescriptor());
+
+ var optionsFormatters = new List()
+ {
+ new XmlDataContractSerializerOutputFormatter(), // This won't be used
+ new JsonOutputFormatter(),
+ };
+
+ var context = GetHttpContext(optionsFormatters);
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
+
var result = new JsonResult(new { foo = "abcd" });
// Act
await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
// Assert
- Assert.Equal(expected, memoryStream.ToArray());
+ Assert.Equal(expected, written);
+ Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
}
[Fact]
- public async Task ExecuteResult_IfNoMatchFoundUsesPassedInFormatter()
+ public async Task ExecuteResultAsync_Null()
{
// Arrange
- var expected = Enumerable.Concat(Encoding.UTF8.GetPreamble(), _abcdUTF8Bytes);
- var memoryStream = new MemoryStream();
- var response = new Mock();
- response.SetupGet(r => r.Body)
- .Returns(memoryStream);
- var context = GetHttpContext(response.Object, registerDefaultFormatter: false);
- var actionContext = new ActionContext(context,
- new RouteData(),
- new ActionDescriptor());
- var testFormatter = new TestJsonFormatter()
- {
- Encoding = Encoding.UTF8
- };
-
- var result = new JsonResult(new { foo = "abcd" }, testFormatter);
+ var expected = _abcdUTF8Bytes;
+
+ var optionsFormatters = new List()
+ {
+ new XmlDataContractSerializerOutputFormatter(), // This won't be used
+ new JsonOutputFormatter(),
+ };
+
+ var context = GetHttpContext(optionsFormatters);
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
+
+ var result = new JsonResult(new { foo = "abcd" });
// Act
await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
// Assert
- Assert.Equal(expected, memoryStream.ToArray());
+ Assert.Equal(expected, written);
+ Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
}
- public async Task ExecuteResult_UsesDefaultFormatter_IfNoneIsRegistered_AndNoneIsPassed()
+ [Fact]
+ public async Task ExecuteResultAsync_OptionsFormatter_Conneg()
{
// Arrange
var expected = _abcdUTF8Bytes;
- var memoryStream = new MemoryStream();
- var response = new Mock();
- response.SetupGet(r => r.Body)
- .Returns(memoryStream);
- var context = GetHttpContext(response.Object, registerDefaultFormatter: false);
- var actionContext = new ActionContext(context,
- new RouteData(),
- new ActionDescriptor());
+
+ var optionsFormatters = new List()
+ {
+ new XmlDataContractSerializerOutputFormatter(), // This won't be used
+ new JsonOutputFormatter(),
+ };
+
+ var context = GetHttpContext(optionsFormatters);
+ context.Request.Accept = "text/json";
+
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
+
var result = new JsonResult(new { foo = "abcd" });
// Act
await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
// Assert
- Assert.Equal(expected, memoryStream.ToArray());
+ Assert.Equal(expected, written);
+ Assert.Equal("text/json;charset=utf-8", context.Response.ContentType);
}
- private HttpContext GetHttpContext(HttpResponse response, bool registerDefaultFormatter = true)
+ [Fact]
+ public async Task ExecuteResultAsync_UsesPassedInFormatter()
{
- var defaultFormatters = registerDefaultFormatter ? new List() { new JsonOutputFormatter() } :
- new List();
- var httpContext = new Mock();
- var mockFormattersProvider = new Mock();
- mockFormattersProvider.SetupGet(o => o.OutputFormatters)
- .Returns(defaultFormatters);
- httpContext.Setup(o => o.RequestServices.GetService(typeof(IOutputFormattersProvider)))
- .Returns(mockFormattersProvider.Object);
- httpContext.SetupGet(o => o.Request.Accept)
- .Returns("");
- httpContext.SetupGet(c => c.Response).Returns(response);
- return httpContext.Object;
+ // Arrange
+ var expected = Enumerable.Concat(Encoding.UTF8.GetPreamble(), _abcdUTF8Bytes);
+
+ var context = GetHttpContext();
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
+
+ var formatter = new JsonOutputFormatter();
+ formatter.SupportedEncodings.Clear();
+
+ // This is UTF-8 WITH BOM
+ formatter.SupportedEncodings.Add(Encoding.UTF8);
+
+ var result = new JsonResult(new { foo = "abcd" }, formatter);
+
+ // Act
+ await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
+
+ // Assert
+ Assert.Equal(expected, written);
+ Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
}
- private class TestJsonFormatter : IOutputFormatter
+ [Fact]
+ public async Task ExecuteResultAsync_UsesPassedInFormatter_ContentTypeSpecified()
{
- public Encoding Encoding { get; set; }
+ // Arrange
+ var expected = _abcdUTF8Bytes;
- public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
- {
- return true;
- }
+ var context = GetHttpContext();
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
- public IReadOnlyList GetSupportedContentTypes(Type declaredType,
- Type runtimeType,
- MediaTypeHeaderValue contentType)
- {
- return null;
- }
+ var formatter = new JsonOutputFormatter();
+ formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/hal+json"));
+
+ var result = new JsonResult(new { foo = "abcd" }, formatter);
+ result.ContentTypes.Add(MediaTypeHeaderValue.Parse("application/hal+json"));
+
+ // Act
+ await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
+
+ // Assert
+ Assert.Equal(expected, written);
+ Assert.Equal("application/hal+json;charset=utf-8", context.Response.ContentType);
+ }
+
+ // If no formatter in options can match the given content-types, then use the one registered
+ // in services
+ [Fact]
+ public async Task ExecuteResultAsync_UsesGlobalFormatter_IfNoFormatterIsConfigured()
+ {
+ // Arrange
+ var expected = _abcdUTF8Bytes;
+
+ var context = GetHttpContext(enableFallback: true);
+ var actionContext = new ActionContext(context, new RouteData(), new ActionDescriptor());
+
+ var result = new JsonResult(new { foo = "abcd" });
+
+ // Act
+ await result.ExecuteResultAsync(actionContext);
+ var written = GetWrittenBytes(context);
+
+ // Assert
+ Assert.Equal(expected, written);
+ Assert.Equal("application/json;charset=utf-8", context.Response.ContentType);
+ }
+
+ private HttpContext GetHttpContext(
+ IReadOnlyList optionsFormatters = null,
+ bool enableFallback = false)
+ {
+ var httpContext = new DefaultHttpContext();
+ httpContext.Response.Body = new MemoryStream();
- public async Task WriteAsync(OutputFormatterContext context)
+ var services = new Mock(MockBehavior.Strict);
+ httpContext.RequestServices = services.Object;
+
+ var mockFormattersProvider = new Mock();
+ mockFormattersProvider
+ .SetupGet(o => o.OutputFormatters)
+ .Returns(optionsFormatters ?? new List());
+
+ services
+ .Setup(s => s.GetService(typeof(IOutputFormattersProvider)))
+ .Returns(mockFormattersProvider.Object);
+
+ // This is the ultimate fallback, it will be used if none of the formatters from options
+ // work.
+ if (enableFallback)
{
- // Override using the selected encoding.
- context.SelectedEncoding = Encoding;
- var jsonFormatter = new JsonOutputFormatter();
- await jsonFormatter.WriteResponseBodyAsync(context);
+ services
+ .Setup(s => s.GetService(typeof(JsonOutputFormatter)))
+ .Returns(new JsonOutputFormatter());
}
+
+ return httpContext;
+ }
+
+ private byte[] GetWrittenBytes(HttpContext context)
+ {
+ context.Response.Body.Seek(0, SeekOrigin.Begin);
+ return Assert.IsType(context.Response.Body).ToArray();
}
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/JsonResultTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/JsonResultTest.cs
new file mode 100644
index 0000000000..64e6b527c5
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/JsonResultTest.cs
@@ -0,0 +1,184 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Builder;
+using Microsoft.AspNet.TestHost;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.FunctionalTests
+{
+ public class JsonResultTest
+ {
+ private readonly IServiceProvider _provider = TestHelper.CreateServices(nameof(BasicWebSite));
+ private readonly Action _app = new BasicWebSite.Startup().Configure;
+
+ [Theory]
+ [InlineData("application/json")]
+ [InlineData("text/json")]
+ public async Task JsonResult_Conneg(string mediaType)
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/Plain";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+ request.Headers.TryAddWithoutValidation("Accept", mediaType);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(mediaType, response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("{\"Message\":\"hello\"}", content);
+ }
+
+ // Using an Accept header can't force Json to not be Json. If your accept header doesn't jive with the
+ // formatters/content-type configured on the result it will be ignored.
+ [Theory]
+ [InlineData("application/xml")]
+ [InlineData("text/xml")]
+ public async Task JsonResult_Conneg_Fails(string mediaType)
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/Plain";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+ request.Headers.TryAddWithoutValidation("Accept", mediaType);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("{\"Message\":\"hello\"}", content);
+ }
+
+ // If the object is null, it will get formatted as JSON. NOT as a 204/NoContent
+ [Fact]
+ public async Task JsonResult_Null()
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/Null";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("null", content);
+ }
+
+ // If the object is a string, it will get formatted as JSON. NOT as text/plain.
+ [Fact]
+ public async Task JsonResult_String()
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/String";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("\"hello\"", content);
+ }
+
+ [Theory]
+ [InlineData("application/json")]
+ [InlineData("text/json")]
+ public async Task JsonResult_CustomFormatter_Conneg(string mediaType)
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/CustomFormatter";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+ request.Headers.TryAddWithoutValidation("Accept", mediaType);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(mediaType, response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("{\"message\":\"hello\"}", content);
+ }
+
+ // Using an Accept header can't force Json to not be Json. If your accept header doesn't jive with the
+ // formatters/content-type configured on the result it will be ignored.
+ [Theory]
+ [InlineData("application/xml")]
+ [InlineData("text/xml")]
+ public async Task JsonResult_CustomFormatter_Conneg_Fails(string mediaType)
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/CustomFormatter";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+ request.Headers.TryAddWithoutValidation("Accept", mediaType);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("{\"message\":\"hello\"}", content);
+ }
+
+ [Fact]
+ public async Task JsonResult_CustomContentType()
+ {
+ // Arrange
+ var server = TestServer.Create(_provider, _app);
+ var client = server.CreateClient();
+
+ var url = "http://localhost/JsonResult/CustomContentType";
+
+ var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+ // Act
+ var response = await client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/message+json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("{\"Message\":\"hello\"}", content);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs b/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs
new file mode 100644
index 0000000000..a88d498fc5
--- /dev/null
+++ b/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.AspNet.Mvc;
+using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
+using Newtonsoft.Json.Serialization;
+
+namespace BasicWebSite.Controllers
+{
+ public class JsonResultController : Controller
+ {
+ public JsonResult Plain()
+ {
+ return Json(new { Message = "hello" });
+ }
+
+ public JsonResult CustomFormatter()
+ {
+ var formatter = new JsonOutputFormatter();
+ formatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+
+ return new JsonResult(new { Message = "hello" }, formatter);
+ }
+
+ public JsonResult CustomContentType()
+ {
+ var formatter = new JsonOutputFormatter();
+ formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/message+json"));
+
+ var result = new JsonResult(new { Message = "hello" }, formatter);
+ result.ContentTypes.Add(MediaTypeHeaderValue.Parse("application/message+json"));
+ return result;
+ }
+
+ public JsonResult Null()
+ {
+ return Json(null);
+ }
+
+ public JsonResult String()
+ {
+ return Json("hello");
+ }
+ }
+}
\ No newline at end of file