web-dev-qa-db-fra.com

Paramètres facultatifs dans le routage d'attributs d'API Web

Je veux gérer POST de l'appel API suivant:

/v1/location/deviceid/appid

Les paramètres supplémentaires proviennent du post-body.

Tout cela fonctionne bien pour moi. Je souhaite maintenant étendre mon code en permettant à "deviceid" et/ou "appid" et/ou BodyData d'être nuls:

/v1/location/deviceid
/v1/location/appid
/v1/location/

Ces 3 URL devraient répondre par le même chemin.

Ma première approche (BodyData requis):

[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody] location_fromuser BodyData)
{
    return repository.AddNewLocation(deviceid, appid, BodyData);
}

Cela ne fonctionne pas et renvoie une erreur de compilation:

"Les paramètres optionnels doivent être à la fin"

Essayez ensuite:

[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post([FromBody] location_fromuser BodyData, string deviceid = null, string appid = null)

Maintenant, ma fonction AddNewLocation () obtient toujours un BodyData=null - même si l'appel envoie le corps.

Enfin, je règle tous les 3 paramètres en option:

[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody location_fromuser BodyData = null)

Ne fonctionne pas:

Le paramètre facultatif BodyData n'est pas pris en charge par FormatterParameterBinding.

Pourquoi est-ce que je veux une solution avec des paramètres optionnels? Mon contrôleur gère uniquement "l'ajout d'un nouvel emplacement" via un POST.

Je veux envoyer sur de mauvaises données mes propres exceptions ou messages d'erreur. Même si l'appel a des valeurs manquantes. Dans ce cas, je veux pouvoir décider de lever une exception ou de définir des valeurs par défaut avec mon code.

80
Oliver Apel

Pour une requête entrante telle que /v1/location/1234, comme vous pouvez l'imaginer, il serait difficile pour l'API Web de déterminer automatiquement si la valeur du segment correspondant à '1234' est liée à appid et non à deviceid.

Je pense que vous devriez changer votre modèle de route pour qu’il ressemble à [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")], puis analyser la deiveOrAppid pour déterminer le type d’id.

Vous devez également rendre les segments du modèle de routage facultatifs, sinon les segments sont considérés comme requis. Notez le caractère ? dans ce cas. Par exemple: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]

153
Kiran Challa

Autre information: si vous voulez utiliser une contrainte de route , imaginez que vous voulez forcer ce paramètre à int type de données, vous devez utiliser la syntaxe suivante:

[Route("v1/location/**{deviceOrAppid:int?}**", Name = "AddNewLocation")]

Le caractère ? est toujours placé avant le dernier }

Pour plus d'informations, voir: Paramètres d'URI facultatifs et valeurs par défaut

42
Tiago Ferreira

Convertir mon commentaire en réponse pour compléter la réponse de @Kiran Chala, car elle semble utile pour le public-

Lorsque nous marquons un paramètre comme facultatif dans l'action uri en utilisant le caractère ?, nous devons alors fournir des valeurs par défaut aux paramètres de la signature de la méthode, comme indiqué ci-dessous:

MyMethod(string name = "someDefaultValue", int? Id = null)

14
RBT