Parametri opzionali nel routing degli attributi delle API Web


93

Voglio gestire il POST della seguente chiamata API:

/v1/location/deviceid/appid

Parametri aggiuntivi provengono dal Post-Body.

Funziona tutto bene per me. Ora desidero estendere il mio codice consentendo a "deviceid" e / o "appid" e / o BodyData di essere nulli:

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

Questi 3 URL dovrebbero rispondere con lo stesso percorso.

Il mio primo approccio (BodyData richiesto):

[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);
}

Questo non funziona e restituisce un errore di compilazione:

"I parametri facoltativi devono essere alla fine"

Prova successiva:

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

Ora la mia funzione AddNewLocation () ottiene sempre un BodyData=null- anche se la chiamata invia il Body.

Infine ho impostato tutti e 3 i parametri opzionali:

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

Non funziona:

Il parametro facoltativo BodyDatanon è supportato da FormatterParameterBinding.

Perché voglio una soluzione con parametri opzionali? Il mio controller gestisce solo "l'aggiunta di una nuova posizione" tramite un POST.

Voglio inviare su dati errati le mie eccezioni o messaggi di errore. Anche se la chiamata ha valori mancanti. In questo caso voglio essere in grado di decidere di lanciare un'eccezione o Impostazione dei valori predefiniti dal mio codice.

Risposte:


182

Per una richiesta in arrivo come /v1/location/1234, come puoi immaginare, sarebbe difficile per l'API Web capire automaticamente se il valore del segmento corrispondente a "1234" è correlato a appide non a deviceid.

Penso che dovresti cambiare il tuo modello di percorso in modo che sia simile [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]e quindi analizzare il deiveOrAppidper capire il tipo di ID.

Inoltre è necessario rendere facoltativi i segmenti nel modello di percorso stesso, altrimenti i segmenti sono considerati obbligatori. Nota il ?carattere in questo caso. Per esempio: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]


58
?all'interno del modello di percorso è quello che stavo cercando. +1
Kal_Torak

4
Non direi che "deviceOrAppId" sia la migliore scelta di design. Penso che l'API dovrebbe sempre sapere per definizione cosa riceverà se possibile.
Niels Brinch

14
Solo per informazione - Quando contrassegniamo un parametro come opzionale nell'azione uri usando il ?carattere, dobbiamo fornire valori predefiniti ai parametri nella firma del metodo, ad esempio MyMethod (string name = "someDefaultValue", int? Id = null).
RBT

@RBT tu da vero MVP, sono rimasto perplesso lì per un minuto. Grazie!
sm

1
Freddo. Sono contento che ti abbia aiutato @sm. Ho convertito il mio commento in una risposta per una migliore visibilità in quanto sembra utile. Sarà un'aggiunta al post di Kiran.
RBT

47

Un'altra informazione: se vuoi usare un Route Constraint , immagina di volere che il parametro abbia un tipo di dati int , quindi devi usare questa sintassi:

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

Il ? il carattere è posto sempre prima dell'ultimo } carattere

Per ulteriori informazioni, vedere: Parametri URI facoltativi e valori predefiniti


18

Convertire il mio commento in una risposta per completare la risposta di @Kiran Chala in quanto sembra utile per il pubblico-

Quando contrassegniamo un parametro come opzionale nell'azione uri usando il ?carattere, dobbiamo fornire valori predefiniti ai parametri nella firma del metodo come mostrato di seguito:

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


Stavo per commentare lo stesso.
Giov.27
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.