Skip to content

Instantly share code, notes, and snippets.

@GREsau
Last active March 31, 2021 15:26
Show Gist options
  • Save GREsau/add50755ac51500dc2ec78d2ace124e2 to your computer and use it in GitHub Desktop.
Save GREsau/add50755ac51500dc2ec78d2ace124e2 to your computer and use it in GitHub Desktop.
// Usage: in Startup.ConfigureServices, add:
// services.AddSingleton<IConfigureOptions<MvcOptions>, JsonPropertyMetadataProviderSetup>();
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.Extensions.Options;
public class JsonPropertyMetadataProviderSetup : IConfigureOptions<MvcOptions>
{
private readonly IOptions<JsonOptions> _jsonOptions;
public JsonPropertyMetadataProviderSetup(IOptions<JsonOptions> jsonOptions)
{
_jsonOptions = jsonOptions;
}
public void Configure(MvcOptions options)
{
var namingPolicy = _jsonOptions.Value.JsonSerializerOptions.PropertyNamingPolicy;
options.ModelMetadataDetailsProviders.Add(new JsonPropertyMetadataProvider(namingPolicy));
}
}
internal class JsonPropertyMetadataProvider : IBindingMetadataProvider, IDisplayMetadataProvider
{
private readonly JsonNamingPolicy _jsonNamingPolicy;
public JsonPropertyMetadataProvider(JsonNamingPolicy jsonNamingPolicy)
{
_jsonNamingPolicy = jsonNamingPolicy;
}
public void CreateBindingMetadata(BindingMetadataProviderContext context)
{
if (context.BindingMetadata.IsBindingAllowed && IsNonControllerProperty(context.Key))
{
var jsonPropertyName = JsonPropertyName(context.Attributes, context.Key);
context.BindingMetadata.BinderModelName ??= jsonPropertyName;
}
}
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
if (IsNonControllerProperty(context.Key))
{
var jsonPropertyName = JsonPropertyName(context.Attributes, context.Key);
context.DisplayMetadata.DisplayName ??= () => jsonPropertyName;
}
}
private static bool IsNonControllerProperty(ModelMetadataIdentity key) =>
key.MetadataKind == ModelMetadataKind.Property
&& !key.ContainerType.IsAssignableTo(typeof(ControllerBase));
private string JsonPropertyName(IReadOnlyList<object> attributes, ModelMetadataIdentity key) =>
attributes.OfType<JsonPropertyNameAttribute>().FirstOrDefault()?.Name
?? _jsonNamingPolicy?.ConvertName(key.Name);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment