web-dev-qa-db-fra.com

Pourquoi devons-nous spécifier FromBody et FromUri?

Pourquoi les attributs FromBody et FromUri sont-ils nécessaires dans l’API Web ASP.NET?

Quelles sont les différences entre utiliser les attributs et ne pas les utiliser?

131
Rajneesh

Lorsque l'API Web ASP.NET appelle une méthode sur un contrôleur, elle doit définir des valeurs pour les paramètres, un processus appelé liaison de paramètres .

Par défaut, Web API utilise les règles suivantes pour lier des paramètres:

  • Si le paramètre est un type "simple" , l'API Web tente d'extraire la valeur de l'URI . Les types simples incluent les types primitifs .NET (int, bool, double, etc.), ainsi que TimeSpan, DateTime, Guid, decimal et string, ainsi que tout type avec un convertisseur de type pouvant convertir une chaîne.

  • Pour les types complexes , Web API tente de lire la valeur dans le corps du message , en utilisant un formateur de type média.

Par conséquent, si vous souhaitez remplacer le comportement par défaut ci-dessus et forcer l'API Web à lire un type complexe à partir de l'URI, ajoutez l'attribut [FromUri] au paramètre. Pour forcer l'API Web à lire un type simple à partir du corps de la demande, ajoutez l'attribut [FromBody] au paramètre.

Donc, pour répondre à votre question, la nécessité des attributs [FromBody] et [FromUri] dans Web API consiste simplement à remplacer, si nécessaire, le comportement par défaut décrit ci-dessus. Notez que vous pouvez utiliser les deux attributs pour une méthode de contrôleur, mais uniquement pour des paramètres différents, comme indiqué ici .

Il y a beaucoupplusinformations sur le Web si vous google "Web API Parameter Binding".

162
djikay

Le comportement par défaut est:

  1. Si le paramètre est une primitive (int, bool, double, ...), l’API Web tente d’obtenir la valeur de URI de la requête HTTP.

  2. Pour types complexes (votre propre objet, par exemple: Person), API Web tente de lire la valeur dans le corps de la requête HTTP.

Donc, si vous avez:

  • un type de primitive dans l'URI, ou
  • un type complexe dans le corps

... alors vous ne devez ajouter aucun attribut (ni [FromBody] ni [FromUri]).

Mais si vous avez un type primitif dans le body , vous devez ensuite ajouter [FromBody] devant votre paramètre de type primitif dans votre méthode de contrôleur WebAPI. (Parce que, par défaut, WebAPI recherche des types primitifs dans l'URI de la requête HTTP.)

Ou, si vous avez un type complexe dans votre URI, vous devez alors ajouter [FromUri]. (Parce que WebAPI recherche par défaut des types complexes dans le corps de la requête HTTP par défaut.)

Types primitifs:

public class UsersController : ApiController
{
    // api/users
    public HttpResponseMessage Post([FromBody]int id)
    {

    }
    // api/users/id
    public HttpResponseMessage Post(int id)
    {

    }       
}

Types complexes:

public class UsersController : ApiController
{       
    // api/users
    public HttpResponseMessage Post(User user)
    {

    }

    // api/users/user
    public HttpResponseMessage Post([FromUri]User user)
    {

    }       
}

Ceci fonctionne tant que vous n'envoyez qu'un seul paramètre dans votre requête HTTP. Lors de l'envoi de plusieurs , vous devez créer un modèle personnalisé qui a tous vos paramètres comme ceci:

public class MyModel
{
    public string MyProperty { get; set; }
    public string MyProperty2 { get; set; }
}

[Route("search")]
[HttpPost]
public async Task<dynamic> Search([FromBody] MyModel model)
{
    // model.MyProperty;
    // model.MyProperty2;
}

De la documentation de Microsoft pour liaison de paramètres dans l'API Web ASP.NET :

Lorsqu'un paramètre a [FromBody], Web API utilise l'en-tête Content-Type pour sélectionner un formateur. Dans cet exemple, le type de contenu est "application/json" et le corps de la demande est une chaîne JSON brute (et non un objet JSON). Au plus un paramètre est autorisé à lire dans le corps du message.

Cela devrait fonctionner:

public HttpResponseMessage Post([FromBody] string name) { ... }

Cela ne fonctionnera pas:

// Caution: This won't work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

La raison de cette règle est que le corps de la demande peut être stocké dans un flux non mis en mémoire tampon qui ne peut être lu qu'une seule fois.

72
Tadej

Lorsqu'un paramètre a [FromBody], Web API utilise l'en-tête Content-Type pour sélectionner un formateur. Dans cet exemple, le type de contenu est "application/json" et le corps de la demande est une chaîne JSON brute (et non un objet JSON).

Au plus un paramètre est autorisé à lire dans le corps du message. Donc cela ne fonctionnera pas:

 // Caution: Will not work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

La raison de cette règle est que le corps de la demande peut être stocké dans un flux non mis en mémoire tampon qui ne peut être lu qu'une seule fois.

Veuillez consulter le site Web pour plus de détails: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api =

11
user5166729

Juste addition aux réponses ci-dessus ..

[FromUri] peut également être utilisé pour lier des types complexes à partir de paramètres uri au lieu de passer des paramètres à partir de la chaîne de requête

Pour ex ..

public class GeoPoint
{
    public double Latitude { get; set; } 
    public double Longitude { get; set; }
}

[RoutePrefix("api/Values")]
public ValuesController : ApiController
{
    [Route("{Latitude}/{Longitude}")]
    public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}

Peut s'appeler comme:

http://localhost/api/values/47.678558/-122.130989
9
Utkarsh Patel