Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonApiSerialiser and core 3.1 #115

Open
alastairtree opened this issue Dec 10, 2019 · 0 comments
Open

JsonApiSerialiser and core 3.1 #115

alastairtree opened this issue Dec 10, 2019 · 0 comments

Comments

@alastairtree
Copy link

Hello

I had a few issues configuring json api serialiser to work on core 3.1. I think it is working now but not sure if there is a better or more supported way? If not this might help others while docs/code gets updated.

using System;
using System.Buffers;
using JsonApiSerializer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace MyApp
{
    // ReSharper disable once UnusedMember.Global
    public static class JsonApiExtensions
    {
        public static IMvcBuilder AddJsonApi(this IMvcBuilder builder, Action<MvcNewtonsoftJsonOptions> setupAction = null)
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();

            builder.Services.TryAddEnumerable(
                ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, ConfigureMvcOptionsForJsonApi>());

            builder.Services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptionsForJsonApi>();

            builder.Services.Configure(setupAction ?? (options => { }));
            return builder;
        }
    }

    public class ConfigureMvcOptionsForJsonApi : IConfigureOptions<MvcOptions>
    {
        private readonly ILoggerFactory loggerFactory;
        private readonly ObjectPoolProvider objectPoolProvider;
        private readonly IOptions<MvcNewtonsoftJsonOptions> newtonsoftOptions;

        public ConfigureMvcOptionsForJsonApi(ILoggerFactory loggerFactory, ObjectPoolProvider objectPoolProvider, IOptions<MvcNewtonsoftJsonOptions> newtonsoftOptions)
        {
            this.loggerFactory = loggerFactory;
            this.objectPoolProvider = objectPoolProvider;
            this.newtonsoftOptions = newtonsoftOptions;
        }

        public void Configure(MvcOptions options)
        {
            var jsonApiSerializerSettings = new JsonApiSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize
            };

            ConfigureInputFormatter(options, jsonApiSerializerSettings, newtonsoftOptions.Value);

            ConfigureOutputFormatter(options, jsonApiSerializerSettings);
        }

        private void ConfigureInputFormatter(MvcOptions options, JsonApiSerializerSettings jsonApiSerializerSettings, MvcNewtonsoftJsonOptions mvcNewtonsoftJsonOptions)
        {
            var jsonApiInputFormatter = new NewtonsoftJsonInputFormatter(
                    loggerFactory.CreateLogger<NewtonsoftJsonInputFormatter>(),
                    jsonApiSerializerSettings, 
                    ArrayPool<char>.Shared, 
                    objectPoolProvider, 
                    options,
                    mvcNewtonsoftJsonOptions);

            jsonApiInputFormatter.SupportedMediaTypes.Clear();
            jsonApiInputFormatter.SupportedMediaTypes.Add(WebConstants.JsonApiContent);

            options.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
            options.InputFormatters.Insert(0, jsonApiInputFormatter);
        }

        private static void ConfigureOutputFormatter(MvcOptions options, JsonApiSerializerSettings jsonApiSerializerSettings)
        {
            var jsonApiOutputFormatter =
                new NewtonsoftJsonOutputFormatter(
                    jsonApiSerializerSettings, 
                    ArrayPool<char>.Shared, 
                    options);

            jsonApiOutputFormatter.SupportedMediaTypes.Clear();
            jsonApiOutputFormatter.SupportedMediaTypes.Add(WebConstants.JsonApiContent);

            options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>();
            options.OutputFormatters.Insert(0, jsonApiOutputFormatter);
        }
    }
}

And then the Json API config can be applied using an extension method in startup.cs, with the option of applying additional config to newtonsoft.json:

public void ConfigureServices(IServiceCollection services)
{
     services.AddOptions();

     services
         .AddMvc()
         .AddJsonApi(opt => opt.AllowInputFormatterExceptionMessages = true); 
         // or just .AddJsonApi()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant