dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.5k stars 10.04k forks source link

Define Json serialization settings per controller. #20630

Open mmichtch opened 4 years ago

mmichtch commented 4 years ago

Issue Title

Setup Json serialization per controller in the ASPNET Core applicaiton.

General

Asp net core has a mechanism to define json serialization options per application using:

        services
            .AddControllers(options => {})
            .AddJsonOptions(options => { /* json options */})
        ;

however there is no way to define json serialization settings per individual controller. The output json can be controlled by parameter of the Json() method in each action, but there is no way to control how input parameters are deserializing from request body on the action.

mkArtakMSFT commented 4 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

mmichtch commented 4 years ago

I see,in this case additional suggestion: it would be nice if mechanism will allow to define settings based on URL mask: something like api/ , odata/ etc

martys commented 3 years ago

I also need to for legacy support, when trying to get the output match exactly the way I need it to be.

twcclegg commented 3 years ago

This causes pain for a service that receives incoming webhooks from multiple 3rd parties (with different naming policies).

ghost commented 2 years ago

Thanks for contacting us.

We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

jaybo commented 2 years ago

Use case: Integrate Stripe (requres snake_case, Newtonsoft.JSON) into aspnetcore V6 app which doesn't use snake_case. How the heck is this supposed to work without per controller serialization settings???

kemsky commented 2 years ago

There are many usecases, specifically for all-in-one apps, usually there are many apis, for different consumers, so it is natural to have slightly different settings per api/controller.

Currently it is very difficult to implement it properly, one has to create complex convention, binder source, intercept action results and so on.

ghost commented 2 years ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

niemyjski commented 2 years ago

I also would love to have this. In my cases I want to control serialization per controller action.

cssack commented 2 years ago

I also would love to have this. In my cases I want to control serialization per controller action.

@niemyjski I currently do it like this: Controller: image

Attribute: image

PostImpatica commented 11 months ago

In .net 6 and with the help of @cssack I used this code:

internal sealed class CustomJsonForBody : ModelBinderAttribute
{

    public CustomJsonForBody() : base(typeof(CustomModelBinder))
    {
        BindingSource = BindingSource.Body;
    }
    private sealed class CustomModelBinder : IModelBinder
    {
        private readonly IModelBinder _bodyModelBinder;

        public CustomModelBinder(IHttpRequestStreamReaderFactory readerFactory, ILoggerFactory loggerFactory, IOptions<MvcOptions> options)
        {
            var formatters = options.Value.InputFormatters.ToList();
            var jsonFormatterIndex = formatters.FindIndex(formatter => formatter is SystemTextJsonInputFormatter);

            var customOptions = new JsonOptions();
            customOptions.JsonSerializerOptions.PropertyNamingPolicy = null;
            customOptions.JsonSerializerOptions.AllowTrailingCommas = true;
            customOptions.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString;
            customOptions.JsonSerializerOptions.IncludeFields = true;
            customOptions.JsonSerializerOptions.Converters.Add(new StringToIntConverter()); // custom converter I'm using
            formatters[jsonFormatterIndex] = new SystemTextJsonInputFormatter(customOptions, loggerFactory.CreateLogger<SystemTextJsonInputFormatter>());
            _bodyModelBinder = new BodyModelBinder(formatters, readerFactory, loggerFactory, options.Value);
        }
        public Task BindModelAsync(ModelBindingContext bindingContext)
         => _bodyModelBinder.BindModelAsync(bindingContext);
    }
}
jkone27 commented 1 month ago

is this going to go in NET9? would be very much needed to be able to define serializer settings for specific controller or specific model classes only, so defining the binder at respone class DTO or controller level (or both)

martincostello commented 1 month ago

I've been seen any changes related to this happening, so that means a minimum of .NET 10.