Make JSON case-insensitive (#10727)
* Make JSON case-insensitive Fixes: #10724 The rationale for this change is that existing .NET client code for the most part uses JSON.NET with its default settings (preserve property casing). This includes the WebAPI client - which we're encouraging everyone to use. It's not really reasonable for us to break everyone using webapi client. * Make separate options and add extension method * fixit * fix build * fix text
This commit is contained in:
parent
1ed5febf93
commit
670865d2a8
|
|
@ -814,6 +814,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public partial interface IRequestSizePolicy : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata
|
||||
{
|
||||
}
|
||||
public partial class JsonOptions
|
||||
{
|
||||
public JsonOptions() { }
|
||||
public System.Text.Json.Serialization.JsonSerializerOptions JsonSerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public partial class JsonResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult
|
||||
{
|
||||
public JsonResult(object value) { }
|
||||
|
|
@ -881,7 +886,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public bool RequireHttpsPermanent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public bool RespectBrowserAcceptHeader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public bool ReturnHttpNotAcceptable { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public System.Text.Json.Serialization.JsonSerializerOptions SerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public int? SslPort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public bool SuppressAsyncSuffixInActionNames { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public bool SuppressImplicitRequiredAttributeForNonNullableReferenceTypes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
|
|
@ -1872,7 +1876,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
}
|
||||
public partial class SystemTextJsonInputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextInputFormatter, Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy
|
||||
{
|
||||
public SystemTextJsonInputFormatter(Microsoft.AspNetCore.Mvc.MvcOptions options) { }
|
||||
public SystemTextJsonInputFormatter(Microsoft.AspNetCore.Mvc.JsonOptions options) { }
|
||||
Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy.ExceptionPolicy { get { throw null; } }
|
||||
public System.Text.Json.Serialization.JsonSerializerOptions SerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
|
|
@ -1880,7 +1884,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
}
|
||||
public partial class SystemTextJsonOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter
|
||||
{
|
||||
public SystemTextJsonOutputFormatter(Microsoft.AspNetCore.Mvc.MvcOptions options) { }
|
||||
public SystemTextJsonOutputFormatter(Microsoft.AspNetCore.Mvc.JsonOptions options) { }
|
||||
public System.Text.Json.Serialization.JsonSerializerOptions SerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
public sealed override System.Threading.Tasks.Task WriteResponseBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context, System.Text.Encoding selectedEncoding) { throw null; }
|
||||
|
|
@ -3026,6 +3030,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddApplicationPart(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Reflection.Assembly assembly) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddControllersAsServices(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddFormatterMappings(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.Formatters.FormatterMappings> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddJsonOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.JsonOptions> configure) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddMvcOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.MvcOptions> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder ConfigureApiBehaviorOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.ApiBehaviorOptions> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcBuilder ConfigureApplicationPartManager(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager> setupAction) { throw null; }
|
||||
|
|
@ -3039,6 +3044,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddControllersAsServices(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddFormatterMappings(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddFormatterMappings(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.Formatters.FormatterMappings> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddJsonOptions(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.JsonOptions> configure) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddMvcOptions(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.MvcOptions> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder ConfigureApiBehaviorOptions(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.ApiBehaviorOptions> setupAction) { throw null; }
|
||||
public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder ConfigureApplicationPartManager(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Action<Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager> setupAction) { throw null; }
|
||||
|
|
|
|||
|
|
@ -42,6 +42,30 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures <see cref="JsonOptions"/> for the specified <paramref name="builder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||
/// <param name="configure">An <see cref="Action"/> to configure the <see cref="JsonOptions"/>.</param>
|
||||
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||
public static IMvcBuilder AddJsonOptions(
|
||||
this IMvcBuilder builder,
|
||||
Action<JsonOptions> configure)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (configure == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configure));
|
||||
}
|
||||
|
||||
builder.Services.Configure(configure);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures <see cref="FormatterMappings"/> for the specified <paramref name="builder"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,30 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures <see cref="JsonOptions"/> for the specified <paramref name="builder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
|
||||
/// <param name="configure">An <see cref="Action"/> to configure the <see cref="JsonOptions"/>.</param>
|
||||
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
||||
public static IMvcCoreBuilder AddJsonOptions(
|
||||
this IMvcCoreBuilder builder,
|
||||
Action<JsonOptions> configure)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (configure == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configure));
|
||||
}
|
||||
|
||||
builder.Services.Configure(configure);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds services to support <see cref="FormatterMappings"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SystemTextJsonInputFormatter"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The <see cref="MvcOptions"/>.</param>
|
||||
public SystemTextJsonInputFormatter(MvcOptions options)
|
||||
/// <param name="options">The <see cref="JsonOptions"/>.</param>
|
||||
public SystemTextJsonInputFormatter(JsonOptions options)
|
||||
{
|
||||
SerializerOptions = options.SerializerOptions;
|
||||
SerializerOptions = options.JsonSerializerOptions;
|
||||
|
||||
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
|
||||
SupportedEncodings.Add(UTF16EncodingLittleEndian);
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
/// <summary>
|
||||
/// Initializes a new <see cref="SystemTextJsonOutputFormatter"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="options">The <see cref="MvcOptions"/>.</param>
|
||||
public SystemTextJsonOutputFormatter(MvcOptions options)
|
||||
/// <param name="options">The <see cref="JsonOptions"/>.</param>
|
||||
public SystemTextJsonOutputFormatter(JsonOptions options)
|
||||
{
|
||||
SerializerOptions = options.SerializerOptions;
|
||||
SerializerOptions = options.JsonSerializerOptions;
|
||||
|
||||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
SupportedEncodings.Add(Encoding.Unicode);
|
||||
|
|
|
|||
|
|
@ -25,21 +25,33 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
private readonly IHttpRequestStreamReaderFactory _readerFactory;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly IOptions<JsonOptions> _jsonOptions;
|
||||
|
||||
public MvcCoreMvcOptionsSetup(IHttpRequestStreamReaderFactory readerFactory)
|
||||
: this(readerFactory, NullLoggerFactory.Instance)
|
||||
: this(readerFactory, NullLoggerFactory.Instance, Options.Create(new JsonOptions()))
|
||||
{
|
||||
}
|
||||
|
||||
public MvcCoreMvcOptionsSetup(IHttpRequestStreamReaderFactory readerFactory, ILoggerFactory loggerFactory)
|
||||
public MvcCoreMvcOptionsSetup(IHttpRequestStreamReaderFactory readerFactory, ILoggerFactory loggerFactory, IOptions<JsonOptions> jsonOptions)
|
||||
{
|
||||
if (readerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(readerFactory));
|
||||
}
|
||||
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
if (jsonOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsonOptions));
|
||||
}
|
||||
|
||||
_readerFactory = readerFactory;
|
||||
_loggerFactory = loggerFactory;
|
||||
_jsonOptions = jsonOptions;
|
||||
}
|
||||
|
||||
public void Configure(MvcOptions options)
|
||||
|
|
@ -66,13 +78,13 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
options.Filters.Add(new UnsupportedContentTypeFilter());
|
||||
|
||||
// Set up default input formatters.
|
||||
options.InputFormatters.Add(new SystemTextJsonInputFormatter(options));
|
||||
options.InputFormatters.Add(new SystemTextJsonInputFormatter(_jsonOptions.Value));
|
||||
|
||||
// Set up default output formatters.
|
||||
options.OutputFormatters.Add(new HttpNoContentOutputFormatter());
|
||||
options.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.OutputFormatters.Add(new StreamOutputFormatter());
|
||||
options.OutputFormatters.Add(new SystemTextJsonOutputFormatter(options));
|
||||
options.OutputFormatters.Add(new SystemTextJsonOutputFormatter(_jsonOptions.Value));
|
||||
|
||||
// Set up ValueProviders
|
||||
options.ValueProviderFactories.Add(new FormValueProviderFactory());
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
Encoding = Encoding.UTF8
|
||||
}.ToString();
|
||||
|
||||
private readonly MvcOptions _mvcOptions;
|
||||
private readonly JsonOptions _options;
|
||||
private readonly ILogger<SystemTextJsonResultExecutor> _logger;
|
||||
|
||||
public SystemTextJsonResultExecutor(
|
||||
IOptions<MvcOptions> mvcOptions,
|
||||
IOptions<JsonOptions> options,
|
||||
ILogger<SystemTextJsonResultExecutor> logger)
|
||||
{
|
||||
_mvcOptions = mvcOptions.Value;
|
||||
_options = options.Value;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
var serializerSettings = result.SerializerSettings;
|
||||
if (serializerSettings == null)
|
||||
{
|
||||
return _mvcOptions.SerializerOptions;
|
||||
return _options.JsonSerializerOptions;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
public class JsonOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="System.Text.Json.Serialization.JsonSerializerOptions"/> used by <see cref="SystemTextJsonInputFormatter"/> and
|
||||
/// <see cref="SystemTextJsonOutputFormatter"/>.
|
||||
/// </summary>
|
||||
public JsonSerializerOptions JsonSerializerOptions { get; } = new JsonSerializerOptions
|
||||
{
|
||||
// Limit the object graph we'll consume to a fixed depth. This prevents stackoverflow exceptions
|
||||
// from deserialization errors that might occur from deeply nested objects.
|
||||
// This value is the same for model binding and Json.Net's serialization.
|
||||
MaxDepth = MvcOptions.DefaultMaxModelBindingRecursionDepth,
|
||||
|
||||
// We're using case-insensitive because there's a TON of code that there that does uses JSON.NET's default
|
||||
// settings (preserve case) - including the WebAPIClient. This worked when we were using JSON.NET + camel casing
|
||||
// because JSON.NET is case-insensitive by default.
|
||||
PropertyNameCaseInsensitive = true,
|
||||
|
||||
// Use camel casing for properties
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,6 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
|
@ -105,18 +103,18 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that detemines if the inference of <see cref="RequiredAttribute"/> for
|
||||
/// for properties and parameters of non-nullable reference types is suppressed. If <c>false</c>
|
||||
/// (the default), then all non-nullable reference types will behave as-if <c>[Required]</c> has
|
||||
/// been applied. If <c>true</c>, this behavior will be suppressed; nullable reference types and
|
||||
/// for properties and parameters of non-nullable reference types is suppressed. If <c>false</c>
|
||||
/// (the default), then all non-nullable reference types will behave as-if <c>[Required]</c> has
|
||||
/// been applied. If <c>true</c>, this behavior will be suppressed; nullable reference types and
|
||||
/// non-nullable reference types will behave the same for the purposes of validation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This option controls whether MVC model binding and validation treats nullable and non-nullable
|
||||
/// reference types differently.
|
||||
/// This option controls whether MVC model binding and validation treats nullable and non-nullable
|
||||
/// reference types differently.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// By default, MVC will treat a non-nullable reference type parameters and properties as-if
|
||||
/// By default, MVC will treat a non-nullable reference type parameters and properties as-if
|
||||
/// <c>[Required]</c> has been applied, resulting in validation errors when no value was bound.
|
||||
/// </para>
|
||||
/// <para>
|
||||
|
|
@ -361,21 +359,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="JsonSerializerOptions"/> used by <see cref="SystemTextJsonInputFormatter"/> and
|
||||
/// <see cref="SystemTextJsonOutputFormatter"/>.
|
||||
/// </summary>
|
||||
public JsonSerializerOptions SerializerOptions { get; } = new JsonSerializerOptions
|
||||
{
|
||||
// Limit the object graph we'll consume to a fixed depth. This prevents stackoverflow exceptions
|
||||
// from deserialization errors that might occur from deeply nested objects.
|
||||
// This value is the same for model binding and Json.Net's serialization.
|
||||
MaxDepth = DefaultMaxModelBindingRecursionDepth,
|
||||
|
||||
// Use camel casing for properties
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
};
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IActionResultExecutor<ObjectResult>>(new ObjectResultExecutor(
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IActionResultExecutor<ObjectResult>>(new ObjectResultExecutor(
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IActionResultExecutor<ObjectResult>>(new ObjectResultExecutor(
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
// Set up default output formatters.
|
||||
MvcOptions.OutputFormatters.Add(new HttpNoContentOutputFormatter());
|
||||
MvcOptions.OutputFormatters.Add(new StringOutputFormatter());
|
||||
MvcOptions.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
MvcOptions.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
// Set up default mapping for json extensions to content type
|
||||
MvcOptions.FormatterMappings.SetMediaTypeMappingForFormat(
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
protected override TextInputFormatter GetInputFormatter()
|
||||
{
|
||||
return new SystemTextJsonInputFormatter(new MvcOptions());
|
||||
return new SystemTextJsonInputFormatter(new JsonOptions());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
{
|
||||
protected override TextOutputFormatter GetOutputFormatter()
|
||||
{
|
||||
return new SystemTextJsonOutputFormatter(new MvcOptions());
|
||||
return new SystemTextJsonOutputFormatter(new JsonOptions());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IActionResultExecutor<ObjectResult>>(new ObjectResultExecutor(
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.OutputFormatters.Add(new StringOutputFormatter());
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new MvcOptions()));
|
||||
options.Value.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonOptions()));
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IActionResultExecutor<ObjectResult>>(new ObjectResultExecutor(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
{
|
||||
protected override IActionResultExecutor<JsonResult> CreateExecutor(ILoggerFactory loggerFactory)
|
||||
{
|
||||
return new SystemTextJsonResultExecutor(Options.Create(new MvcOptions()), loggerFactory.CreateLogger<SystemTextJsonResultExecutor>());
|
||||
return new SystemTextJsonResultExecutor(Options.Create(new JsonOptions()), loggerFactory.CreateLogger<SystemTextJsonResultExecutor>());
|
||||
}
|
||||
|
||||
protected override object GetIndentedSettings()
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
|
|||
{
|
||||
internal class SystemTextJsonHelper : IJsonHelper
|
||||
{
|
||||
private readonly MvcOptions _mvcOptions;
|
||||
private readonly JsonOptions _options;
|
||||
|
||||
public SystemTextJsonHelper(IOptions<MvcOptions> mvcOptions)
|
||||
public SystemTextJsonHelper(IOptions<JsonOptions> options)
|
||||
{
|
||||
_mvcOptions = mvcOptions.Value;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
|
|||
{
|
||||
// JsonSerializer always encodes non-ASCII chars, so we do not need
|
||||
// to do anything special with the SerializerOptions
|
||||
var json = JsonSerializer.ToString(value, _mvcOptions.SerializerOptions);
|
||||
var json = JsonSerializer.ToString(value, _options.JsonSerializerOptions);
|
||||
return new HtmlString(json);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
@ -12,8 +10,8 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
|
|||
{
|
||||
protected override IJsonHelper GetJsonHelper()
|
||||
{
|
||||
var mvcOptions = new MvcOptions { SerializerOptions = { PropertyNamingPolicy = JsonNamingPolicy.CamelCase } };
|
||||
return new SystemTextJsonHelper(Options.Create(mvcOptions));
|
||||
var options = new JsonOptions() { JsonSerializerOptions = { PropertyNamingPolicy = JsonNamingPolicy.CamelCase } };
|
||||
return new SystemTextJsonHelper(Options.Create(options));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Net.Http;
|
|||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using FormatterWebSite.Controllers;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -98,6 +99,28 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Equal(expected, responseBody);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task JsonInputFormatter_RoundtripsPocoModel()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new JsonFormatterController.SimpleModel()
|
||||
{
|
||||
Id = 18,
|
||||
Name = "James",
|
||||
StreetName = "JnK",
|
||||
};
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsJsonAsync("http://localhost/JsonFormatter/RoundtripSimpleModel/", expected);
|
||||
var actual = await response.Content.ReadAsAsync<JsonFormatterController.SimpleModel>();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expected.Id, actual.Id);
|
||||
Assert.Equal(expected.Name, actual.Name);
|
||||
Assert.Equal(expected.StreetName, actual.StreetName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task JsonInputFormatter_Returns415UnsupportedMediaType_ForEmptyContentType()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ namespace BasicWebSite
|
|||
// Set up application services
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddRouting();
|
||||
|
||||
services.AddMvc()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest)
|
||||
.AddNewtonsoftJson()
|
||||
|
|
|
|||
|
|
@ -64,5 +64,20 @@ namespace FormatterWebSite.Controllers
|
|||
|
||||
return Content(value.ToString());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult<SimpleModel> RoundtripSimpleModel([FromBody] SimpleModel model)
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
public class SimpleModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string StreetName { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue