Add JsonHelper for serializing JSON in views

- remove NotNull from JsonHelper Serialize
This commit is contained in:
James Newton-King 2015-05-09 10:29:56 +00:00 committed by Doug Bunting
parent 40794fcc33
commit ab4cd5c4c4
21 changed files with 200 additions and 4 deletions

View File

@ -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
{
/// <summary>
/// Base JSON helpers.
/// </summary>
public interface IJsonHelper
{
/// <summary>
/// Returns serialized JSON for the <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to serialize as JSON.</param>
/// <returns>A new <see cref="HtmlString"/> containing the serialized JSON.</returns>
HtmlString Serialize(object value);
/// <summary>
/// Returns serialized JSON for the <paramref name="value"/>.
/// </summary>
/// <param name="value">The value to serialize as JSON.</param>
/// <param name="serializerSettings">The <see cref="JsonSerializerSettings"/> to be used by the serializer.</param>
/// <returns>A new <see cref="HtmlString"/> containing the serialized JSON.</returns>
HtmlString Serialize(object value, [NotNull] JsonSerializerSettings serializerSettings);
}
}

View File

@ -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
{
/// <summary>
/// Default implementation of <see cref="IJsonHelper"/>.
/// </summary>
public class JsonHelper : IJsonHelper
{
private readonly JsonOutputFormatter _jsonOutputFormatter;
/// <summary>
/// Initializes a new instance of <see cref="JsonHelper"/> that is backed by <paramref name="jsonOutputFormatter"/>.
/// </summary>
/// <param name="jsonOutputFormatter">The <see cref="JsonOutputFormatter"/> used to serialize JSON.</param>
public JsonHelper([NotNull] JsonOutputFormatter jsonOutputFormatter)
{
_jsonOutputFormatter = jsonOutputFormatter;
}
/// <inheritdoc />
public HtmlString Serialize(object value)
{
return SerializeInternal(_jsonOutputFormatter, value);
}
/// <inheritdoc />
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());
}
}
}

View File

@ -33,6 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private static readonly Chunk[] _defaultInheritedChunks = new[]
{
new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel>", HtmlHelperPropertyName),
new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IJsonHelper", "Json"),
new InjectChunk("Microsoft.AspNet.Mvc.IViewComponentHelper", "Component"),
new InjectChunk("Microsoft.AspNet.Mvc.IUrlHelper", "Url"),
};

View File

@ -144,6 +144,7 @@ namespace Microsoft.Framework.DependencyInjection
// View and rendering helpers
services.TryAdd(ServiceDescriptor.Transient<IHtmlHelper, HtmlHelper>());
services.TryAdd(ServiceDescriptor.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)));
services.TryAdd(ServiceDescriptor.Transient<IJsonHelper, JsonHelper>());
services.TryAdd(ServiceDescriptor.Scoped<IUrlHelper, UrlHelper>());
// Only want one ITagHelperActivator so it can cache Type activation information. Types won't conflict.

View File

@ -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 <b>Smith</b>"
});
var expectedBody = string.Format(@"<script type=""text/javascript"">" + Environment.NewLine +
@" var json = {0};" + Environment.NewLine +
@"</script>", 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 <b>Smith</b>"
}, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
var expectedBody = string.Format(@"<script type=""text/javascript"">" + Environment.NewLine +
@" var json = {0};" + Environment.NewLine +
@"</script>", 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<object[]> HtmlHelperLinkGenerationData
{
get

View File

@ -121,16 +121,16 @@ namespace Microsoft.AspNet.Mvc.Razor
BuildLineMapping(documentAbsoluteIndex: 139,
documentLineIndex: 4,
documentCharacterIndex: 17,
generatedAbsoluteIndex: 2105,
generatedLineIndex: 53,
generatedAbsoluteIndex: 2241,
generatedLineIndex: 55,
generatedCharacterIndex: 95,
contentLength: 3),
BuildLineMapping(
documentAbsoluteIndex: 166,
documentLineIndex: 5,
documentCharacterIndex: 18,
generatedAbsoluteIndex: 2418,
generatedLineIndex: 59,
generatedAbsoluteIndex: 2554,
generatedLineIndex: 61,
generatedCharacterIndex: 87,
contentLength: 5),
};

View File

@ -17,6 +17,8 @@
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -32,6 +32,8 @@ using MyNamespace
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -38,6 +38,8 @@
#line hidden
{ get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -54,6 +54,8 @@
#line hidden
{ get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -24,6 +24,8 @@
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -40,6 +40,8 @@
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -18,6 +18,8 @@ namespace Asp
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -26,6 +26,8 @@ using MyNamespace
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -26,6 +26,8 @@ namespace Asp
[Microsoft.AspNet.Mvc.ActivateAttribute]
public MyService<MyModel> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -30,6 +30,8 @@ namespace Asp
[Microsoft.AspNet.Mvc.ActivateAttribute]
public MyService<MyModel> Html2 { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -24,6 +24,8 @@ namespace Asp
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<System.Collections.IEnumerable> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -33,6 +33,8 @@ namespace Asp
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<DateTime> Html { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.Rendering.IJsonHelper Json { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; }
[Microsoft.AspNet.Mvc.ActivateAttribute]
public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; }

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using BasicWebSite.Models;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.WebUtilities;
@ -54,6 +55,28 @@ namespace BasicWebSite.Controllers
return Task.FromResult(true);
}
public IActionResult JsonHelperInView()
{
Person person = new Person
{
Id = 9000,
Name = "John <b>Smith</b>"
};
return View(person);
}
public IActionResult JsonHelperWithSettingsInView()
{
Person person = new Person
{
Id = 9000,
Name = "John <b>Smith</b>"
};
return View(person);
}
public IActionResult JsonTextInView()
{
return View();

View File

@ -0,0 +1,3 @@
<script type="text/javascript">
var json = @Json.Serialize(Model);
</script>

View File

@ -0,0 +1,5 @@
@using Newtonsoft.Json
@using Newtonsoft.Json.Serialization
<script type="text/javascript">
var json = @Json.Serialize(Model, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
</script>