web-dev-qa-db-fra.com

Modifier les paramètres de sérialisation JSON d'un seul contrôleur ASP.NET Core

J'ai deux contrôleurs de contrôleur: ControllerA et ControllerB. La classe de base de chaque contrôleur est Controller.

ControllerA doit retourner JSON dans le format par défaut (camelCase). ControllerB doit renvoyer des données dans un format JSON différent: snake_case.

Comment puis-je implémenter cela dans ASP.NET Core 2.1?

J'ai essayé le startup avec:

services
    .AddMvc()
    .AddJsonOptions(options =>
    {
        options.SerializerSettings.Converters.Add(new StringEnumConverter());
        options.SerializerSettings.ContractResolver = new DefaultContractResolver()
        {
            NamingStrategy = new SnakeCaseNamingStrategy()
        };
    })
    .AddControllersAsServices();

Mais cela changera la sérialisation pour les contrôleurs tous, pas seulement pour ControllerB. Comment puis-je configurer ou annoter cette fonction pour 1 contrôleur?

10
Kees C. Bakker

Vous pouvez y parvenir avec une combinaison d'un Action Filter et d'un Output Formatter . Voici un exemple de ce à quoi pourrait ressembler le filtre d'action:

public class SnakeCaseAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext ctx)
    {
        if (ctx.Result is ObjectResult objectResult)
        {
            objectResult.Formatters.Add(new JsonOutputFormatter(
                new JsonSerializerSettings
                {
                    ContractResolver = new DefaultContractResolver
                    {
                        NamingStrategy = new SnakeCaseNamingStrategy()
                    }
                },
                ctx.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>()));
        }
    }
}

En utilisant OnActionExecuted, le code s'exécute après l'action correspondante et vérifie d'abord si le résultat est un ObjectResult (qui s'applique également à OkObjectResult grâce à l'héritage). S'il s'agit d'un ObjectResult, le filtre ajoute simplement une version personnalisée d'un JsonOutputFormatter qui sérialisera les propriétés à l'aide de SnakeCaseNamingStrategy. Le deuxième paramètre du constructeur JsonOutputFormatter est extrait du conteneur DI.

Pour utiliser ce filtre, appliquez-le simplement au contrôleur approprié:

[SnakeCase]
public class ControllerB : Controller { }

Remarque: Vous voudrez peut-être créer le JsonOutputFormatter à l'avance quelque part, par exemple - je ne suis pas allé aussi loin dans l'exemple car c'est secondaire à la question à portée de main.

7
Kirk Larkin