diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/IJsonHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/IJsonHelper.cs
new file mode 100644
index 0000000000..e9a3203806
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/IJsonHelper.cs
@@ -0,0 +1,29 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.Framework.Internal;
+using Newtonsoft.Json;
+
+namespace Microsoft.AspNet.Mvc.Rendering
+{
+ ///
+ /// Base JSON helpers.
+ ///
+ public interface IJsonHelper
+ {
+ ///
+ /// Returns serialized JSON for the .
+ ///
+ /// The value to serialize as JSON.
+ /// A new containing the serialized JSON.
+ HtmlString Serialize(object value);
+
+ ///
+ /// Returns serialized JSON for the .
+ ///
+ /// The value to serialize as JSON.
+ /// The to be used by the serializer.
+ /// A new containing the serialized JSON.
+ HtmlString Serialize(object value, [NotNull] JsonSerializerSettings serializerSettings);
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/JsonHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/JsonHelper.cs
new file mode 100644
index 0000000000..789b4783c8
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/JsonHelper.cs
@@ -0,0 +1,53 @@
+// Copyright (c) .NET Foundation. 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.Globalization;
+using System.IO;
+using Newtonsoft.Json;
+using Microsoft.Framework.Internal;
+
+namespace Microsoft.AspNet.Mvc.Rendering
+{
+ ///
+ /// Default implementation of .
+ ///
+ public class JsonHelper : IJsonHelper
+ {
+ private readonly JsonOutputFormatter _jsonOutputFormatter;
+
+ ///
+ /// Initializes a new instance of that is backed by .
+ ///
+ /// The used to serialize JSON.
+ public JsonHelper([NotNull] JsonOutputFormatter jsonOutputFormatter)
+ {
+ _jsonOutputFormatter = jsonOutputFormatter;
+ }
+
+ ///
+ public HtmlString Serialize(object value)
+ {
+ return SerializeInternal(_jsonOutputFormatter, value);
+ }
+
+ ///
+ public HtmlString Serialize(object value, [NotNull] JsonSerializerSettings serializerSettings)
+ {
+ var jsonOutputFormatter = new JsonOutputFormatter
+ {
+ SerializerSettings = serializerSettings
+ };
+
+ return SerializeInternal(jsonOutputFormatter, value);
+ }
+
+ private HtmlString SerializeInternal(JsonOutputFormatter jsonOutputFormatter, object value)
+ {
+ var stringWriter = new StringWriter(CultureInfo.InvariantCulture);
+ jsonOutputFormatter.WriteObject(stringWriter, value);
+
+ return new HtmlString(stringWriter.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs
index 149a93bdb8..7442a7a239 100644
--- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs
+++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs
@@ -33,6 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private static readonly Chunk[] _defaultInheritedChunks = new[]
{
new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper", HtmlHelperPropertyName),
+ new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IJsonHelper", "Json"),
new InjectChunk("Microsoft.AspNet.Mvc.IViewComponentHelper", "Component"),
new InjectChunk("Microsoft.AspNet.Mvc.IUrlHelper", "Url"),
};
diff --git a/src/Microsoft.AspNet.Mvc/MvcServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc/MvcServiceCollectionExtensions.cs
index 17c9c4e6b3..0091994a11 100644
--- a/src/Microsoft.AspNet.Mvc/MvcServiceCollectionExtensions.cs
+++ b/src/Microsoft.AspNet.Mvc/MvcServiceCollectionExtensions.cs
@@ -144,6 +144,7 @@ namespace Microsoft.Framework.DependencyInjection
// View and rendering helpers
services.TryAdd(ServiceDescriptor.Transient());
services.TryAdd(ServiceDescriptor.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)));
+ services.TryAdd(ServiceDescriptor.Transient());
services.TryAdd(ServiceDescriptor.Scoped());
// Only want one ITagHelperActivator so it can cache Type activation information. Types won't conflict.
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/BasicTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/BasicTests.cs
index 0ab3fc9552..2e6aa48800 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/BasicTests.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/BasicTests.cs
@@ -12,6 +12,7 @@ using BasicWebSite;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
@@ -209,6 +210,62 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal(expectedBody, actualBody);
}
+ [Fact]
+ public async Task JsonHelper_RendersJson()
+ {
+ // Arrange
+ var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
+ var client = new HttpClient(server.CreateHandler(), false);
+
+ var json = JsonConvert.SerializeObject(new BasicWebSite.Models.Person()
+ {
+ Id = 9000,
+ Name = "John Smith"
+ });
+
+ var expectedBody = string.Format(@"", json);
+
+ // Act
+ var response = await client.GetAsync("https://localhost/Home/JsonHelperInView");
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("text/html", response.Content.Headers.ContentType.MediaType);
+
+ var actualBody = await response.Content.ReadAsStringAsync();
+ Assert.Equal(expectedBody, actualBody);
+ }
+
+ [Fact]
+ public async Task JsonHelperWithSettings_RendersJson()
+ {
+ // Arrange
+ var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
+ var client = new HttpClient(server.CreateHandler(), false);
+
+ var json = JsonConvert.SerializeObject(new BasicWebSite.Models.Person()
+ {
+ Id = 9000,
+ Name = "John Smith"
+ }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
+
+ var expectedBody = string.Format(@"", json);
+
+ // Act
+ var response = await client.GetAsync("https://localhost/Home/JsonHelperWithSettingsInView");
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("text/html", response.Content.Headers.ContentType.MediaType);
+
+ var actualBody = await response.Content.ReadAsStringAsync();
+ Assert.Equal(expectedBody, actualBody);
+ }
+
public static IEnumerable