Search code examples
c#asp.net-corejson-serialization

AspNet Core - input/output JSON serialization settings at Controller Level


My application requires the (almost default) JSON serialization settings:

services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddJsonOptions(options =>
            {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
            });

For one controller only, I need to use a different naming strategy for both input (where I use model binding with [FromBody] myComplexObject and output with

options.SerializerSettings.ContractResolver = new DefaultContractResolver();

My question is virtually identical to Web API: Configure JSON serializer settings on action or controller level with the exception that I'm asking for AspNet Core 2.2+, in which IControllerConfiguration is no longer existent.

The Core 2.1+ equivalent question has a response here: Configure input/output formatters on controllers with ASP.NET Core 2.1

The answers there appear slightly fragmented or incomplete - it's hard to imagine that there is no easier way to achieve this. Would anyone have an idea on how to use a DefaultContractResolver for all input and output within a single controller?


Solution

  • The answer you link works well enough, but you can extend it further by wrapping it in an attribute that you can apply to any action or controller. For example:

    public class JsonConfigFilterAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            if (context.Result is ObjectResult objectResult)
            {
                var serializerSettings = new JsonSerializerSettings
                {
                    ContractResolver = new DefaultContractResolver()
                };
    
                var jsonFormatter = new JsonOutputFormatter(
                    serializerSettings, 
                    ArrayPool<char>.Shared);
    
                objectResult.Formatters.Add(jsonFormatter);
            }
    
            base.OnResultExecuting(context);
        }
    }
    

    And just add it to action methods or controllers:

    [JsonConfigFilter]
    public ActionResult<Foo> SomeAction()
    {
        return new Foo
        {
            Bar = "hello"
        };
    }