Renvoyer le résultat JSON avec le code d'état personnalisé dans ASP.NET Core

Contrôlez le format des réponses ASP.NET Core et apprenez à renvoyer un résultat JSON avec un code d'état personnalisé à l'aide de formateurs ou directement à partir de l'action.
Lorsque vous créez des API HTTP, vous voulez avoir le contrôle sur la façon dont vous répondez aux demandes en termes de modification des codes d'état et du format du corps. Dans cet article de blog, nous verrons comment nous pouvons contrôler la réponse JSON en personnalisant le code d'état dans ASP.NET Core.
Comment ASP.NET Core décide du format de réponse
Voyons d'abord comment un résultat JSON est en fait produit par ASP.NET Core, ce qui nous aidera à comprendre le mécanisme derrière le formatage des réponses. Lorsque nous développons un projet ASP.NET Core avec la configuration de l'API Web avec la commande CLI dotnet ci-dessous:
dotnet new webapi --no-https --auth = Aucun
Notre fichier startup.cs ressemblera à ceci:
public class Startup
{
public Startup ( IConfiguration configuration )
{
Configuration = configuration ;
}
public IConfiguration Configuration { get ; }
public void ConfigureServices ( IServiceCollection services )
{
services . AddControllers () ;
}
public void Configure ( IApplicationBuilder app IWebHostEnvironment env )
{
if ( env . IsDevelopment () )
{
app . UseDeveloperExceptionPage () ;
}
app . UseRouting () ;
app . UseAuthorization () ;
app . UseEndpoints ( endpoints = >
{
endpoints . MapControllers () ;
} ) ;
}
}
Nous avons également un exemple de fichier de contrôleur nommé WeatherForecastController.cs
qui a la forme ci-dessous:
[ ApiController ]
[ Route ] ( "[controller]" ) ]
public class WeatherForecastController : ControllerBase
{
private static readonly string [] Summaries = new [] [19659014] {
"Freezing" "Bracing" "Chilly" "Cool" "Mild" [19659013] "Warm" "Balmy" "Hot" "Sweltering" "Scorching" [19659014]} ;
private readonly ILogger < WeatherForecastController > _logger ;
public WeatherForecastController ILogger < WeatherForecastController > logger )
{
_logger = logger ;
}
[ HttpGet ]
public IEnumerable < WeatherForecast > [19659012] Get ()
{
var rng = new Random () ;
return Enumerable . Range ( 1 5 ) . Sélectionnez ( index = > nouveau WeatherForecast
{
Date = DateHeure . Now . AddDays ( index )
TemperatureC = rng . Next ( - 20 55 )
Résumé = Résumés [ rng . Suivant ( Résumés . Longueur ) ] [19659041]} )
. ToArray () ;
}
}
Ceci a les bases avec lesquelles nous pouvons travailler pour comprendre comment la réponse est structurée en termes de format et de code d'état.
Lorsque nous configurons ASP.NET Core avec services.AddControllers
cela ajoute les OutputFormatters intégrés, qui sont utilisés pour écrire un objet dans le flux de sortie:
- Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter
- Microsoft.AspNetCore.Mvatterc.Formatters.StringOutFput
- ] Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter
- Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter
Ces formateurs de sortie permettent à une action de renvoyer n'importe quelle valeur de retour d'objet. Le formateur est sélectionné ici par le biais du processus appelé négociation de contenu qui se produit lorsque le client spécifie un en-tête Accept.
Regardons cela avec un exemple. Avec la modification ci-dessous, nous ajouterons le formateur de sortie XML à la liste des formateurs pris en charge:
public void ConfigureServices ( IServiceCollection services )
{
services . AddControllers () . AddXmlSerializerFormatters () ;
}
Maintenant, nous verrons que la réponse sera écrite en XML lorsque nous spécifierons que nous voulons recevoir le corps de la réponse en XML via l'en-tête Accept:
curl -v -H "Accept: application / xml" http : // localhost: 5000 / WeatherForecast
* Essayer :: 1 ...
* TCP_NODELAY défini
* Connecté au port 5000 localhost (:: 1) (# 0)
> GET / WeatherForecast HTTP / 1.1
> Hôte: localhost: 5000
> Agent utilisateur: curl / 7.54.0
> Accepter: application / xml
>
<HTTP / 1.1 200 OK
<Date: lun, 13 janvier 2020 21:06:32 GMT
<Type de contenu: application / xml; jeu de caractères = utf-8
<Serveur: Kestrel
<Content-Longueur: 829
<
* La connexion n ° 0 à l'hôte localhost est restée intacte
2020-01-14T21: 06: 32.786281 + 00: 00 3 Chaud 2020-01-15T21: 06: 32.794902 + 00: 00 36 Doux ] 2020-01-16T21: 06: 32.794907 + 00: 00 -14 Scorching 2020-01-17T21: 06: 32.794908 + 00: 00 5 Chilly 2020-01-18T21: 06: 32.794908 + 00: 00 -13 Torride
La réponse sera au format JSON lorsque nous spécifions l'en-tête Accept comme application / json:
curl -v -H "Accept: application / json" http: // localhost: 5000 / WeatherForecast
* Essayer :: 1 ...
* TCP_NODELAY défini
* Connecté au port 5000 localhost (:: 1) (# 0)
> GET / WeatherForecast HTTP / 1.1
> Hôte: localhost: 5000
> User-Agent: curl / 7.54.0
> Accepter: application / json
>
<HTTP / 1.1 200 OK
<Date: Lun, 13 janvier 2020 21:09:05 GMT
<Type de contenu: application / json; jeu de caractères = utf-8
<Serveur: Kestrel
<Transfert-Encodage: fragmenté
<
* La connexion n ° 0 à l'hôte localhost est restée intacte
[{"date":"2020-01-14T21:09:05.635107+00:00","temperatureC":4,"temperatureF":39,"summary":"Hot"},{"date":"2020-01-15T21:09:05.635279+00:00","temperatureC":-8,"temperatureF":18,"summary":"Scorching"},{"date":"2020-01-16T21:09:05.635281+00:00","temperatureC":42,"temperatureF":107,"summary":"Balmy"},{"date":"2020-01-17T21:09:05.635281+00:00","temperatureC":27,"temperatureF":80,"summary":"Chilly"},{"date":"2020-01-18T21:09:05.635282+00:00","temperatureC":44,"temperatureF":111,"summary":"Warm"}]%
En plus de renvoyer des POCO (Plain Old CLR Objects) et de laisser la négociation de contenu décider quel formateur de sortie choisir, vous pouvez également renvoyer un IActionResult qui définit un contrat qui représente le résultat d'une méthode d'action , à partir de l'action du contrôleur qui peut vous permettre d'avoir un contrôle direct sur le type de retour. Par exemple, l'implémentation d'aide intégrée IActionResult JsonResult renvoie des données au format JSON, quel que soit l'en-tête Accept.
[ HttpGet ]
public IActionResult Get ()
{
var rng = new Random () ;
var result = Enumerable . Range ( 1 5 ) . Sélectionnez ] ( index = > nouveau WeatherForecast
{
Date = DateHeure . Now . AddDays ( index )
TemperatureC = rng . Next ( - 20 55 )
Résumé = Résumés [ rng . Suivant ( Résumés . Longueur ) ] [19659014]} )
. ToArray () ;
return new JsonResult ( result ) ;
}
curl -v -H "Accepter: application / xml" http: // localhost: 5000 / WeatherForecast
* Essayer :: 1 ...
* TCP_NODELAY défini
* Connecté au port 5000 localhost (:: 1) (# 0)
> GET / WeatherForecast HTTP / 1.1
> Hôte: localhost: 5000
> User-Agent: curl / 7.54.0
> Accepter: application / xml
>
<HTTP / 1.1 200 OK
<Date: lun, 13 janvier 2020 21:18:39 GMT
<Type de contenu: application / json; jeu de caractères = utf-8
<Serveur: Kestrel
<Transfert-Encodage: fragmenté
<
* La connexion n ° 0 à l'hôte localhost est restée intacte
[{"date":"2020-01-14T21:18:40.678848+00:00","temperatureC":12,"temperatureF":53,"summary":"Scorching"},{"date":"2020-01-15T21:18:40.685278+00:00","temperatureC":23,"temperatureF":73,"summary":"Chilly"},{"date":"2020-01-16T21:18:40.685283+00:00","temperatureC":24,"temperatureF":75,"summary":"Cool"},{"date":"2020-01-17T21:18:40.685284+00:00","temperatureC":-10,"temperatureF":15,"summary":"Hot"},{"date":"2020-01-18T21:18:40.685284+00:00","temperatureC":-5,"temperatureF":24,"summary":"Bracing"}]%
Modification du code d’état de réponse
Voyons maintenant comment nous pouvons modifier le code d’état de réponse. Avec tous les cas que nous avons mentionnés ci-dessus, nous pouvons simplement définir Response.StatusCode
juste avant de renvoyer le résultat au code de statut approprié avec lequel nous voulons répondre:
[ HttpGet ]
public IActionResult Get ()
{
var rng = new Random ( ]) ;
var result = Enumerable . Range ( 1 5 ) . Sélectionnez ( index = > new WeatherForecast
{
Date = DateHeure . Now . AddDays ( index )
TemperatureC = rng . Next ( - 20 55 )
Résumé = Résumés [ rng . Suivant ( Résumés . Longueur ) ] [19659014]} )
. ToArray () ;
Réponse . StatusCode = StatusCodes . Status400BadRequest ;
return new JsonResult ( result ) ;
}
Vous pouvez voir dans l'exemple de requête ci-dessous que nous récupérons la réponse avec le code d'état 400:
curl -v -H "Accept: application / json" http: // localhost: 5000 / WeatherForecast
* Essayer :: 1 ...
* TCP_NODELAY défini
* Connecté au port 5000 localhost (:: 1) (# 0)
> GET / WeatherForecast HTTP / 1.1
> Hôte: localhost: 5000
> Agent utilisateur: curl / 7.54.0
> Accepter: application / json
>
<HTTP / 1.1 400 Mauvaise requête
<Date: lun 13 janvier 2020 21:34:53 GMT
<Type de contenu: application / json; jeu de caractères = utf-8
<Serveur: Kestrel
<Transfert-Encodage: fragmenté
<
* La connexion n ° 0 à l'hôte localhost est restée intacte
[{"date":"2020-01-14T21:34:54.415857+00:00","temperatureC":21,"temperatureF":69,"summary":"Sweltering"},{"date":"2020-01-15T21:34:54.4239+00:00","temperatureC":-6,"temperatureF":22,"summary":"Freezing"},{"date":"2020-01-16T21:34:54.423907+00:00","temperatureC":9,"temperatureF":48,"summary":"Mild"},{"date":"2020-01-17T21:34:54.423907+00:00","temperatureC":51,"temperatureF":123,"summary":"Freezing"},{"date":"2020-01-18T21:34:54.423908+00:00","temperatureC":49,"temperatureF":120,"summary":"Hot"}]%
En plus de cette manière simple de définir le code d'état, nous avons également des méthodes d'assistance sur l'objet ControllerBase, ce qui nous donne la possibilité de façonner une réponse. Par exemple, la méthode Conflict crée un ConflictObjectResult qui produit une réponse Status409Conflict .
[ HttpGet ]
public IActionResult Get ()
{
var rng = new Random () ;
var result = Enumerable . Range ( 1 5 ) . [19659025] Sélectionnez ( index = > new WeatherForecast
{
Date = DateHeure . Now . AddDays ( index )
TemperatureC = rng . Next ( - 20 55 )
Résumé = Résumés [ rng . Suivant ( Résumés . Longueur ) ] [19659014]} )
. ToArray () ;
return Conflict ( result ) ;
}
curl -v -H "Accepter: application / json" http: // localhost: 5000 / WeatherForecast
* Essayer :: 1 ...
* TCP_NODELAY défini
* Connecté au port 5000 localhost (:: 1) (# 0)
> GET / WeatherForecast HTTP / 1.1
> Hôte: localhost: 5000
> User-Agent: curl / 7.54.0
> Accepter: application / json
>
<HTTP / 1.1 409 Conflit
<Date: lun, 13 janvier 2020 21:38:03 GMT
<Type de contenu: application / json; jeu de caractères = utf-8
<Serveur: Kestrel
<Transfert-Encodage: fragmenté
<
* La connexion n ° 0 à l'hôte localhost est restée intacte
[{"date":"2020-01-14T21:38:04.665259+00:00","temperatureC":-19,"temperatureF":-2,"summary":"Chilly"},{"date":"2020-01-15T21:38:04.673328+00:00","temperatureC":47,"temperatureF":116,"summary":"Bracing"},{"date":"2020-01-16T21:38:04.673334+00:00","temperatureC":28,"temperatureF":82,"summary":"Chilly"},{"date":"2020-01-17T21:38:04.673335+00:00","temperatureC":17,"temperatureF":62,"summary":"Warm"},{"date":"2020-01-18T21:38:04.673335+00:00","temperatureC":49,"temperatureF":120,"summary":"Bracing"}]%
Dans ce cas, peu importe ce que nous avons défini Response.StatusCode
dans l'action, il serait remplacé par la méthode d'assistance Conflict
.
Source link