Optionale Parameter im Web-API-Attribut-Routing

89

Ich möchte den POST des folgenden API-Aufrufs verarbeiten:

/v1/location/deviceid/appid

Zusätzliche Parameter kommen vom Post-Body.

Das alles funktioniert gut für mich. Jetzt möchte ich meinen Code erweitern, indem ich zulasse, dass "deviceid" und / oder "appid" und / oder BodyData null sind:

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

Diese 3 URLs sollten auf demselben Weg antworten.

Mein erster Ansatz (BodyData erforderlich):

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

Dies funktioniert nicht und gibt einen Kompilierungsfehler zurück:

"Optionale Parameter müssen am Ende stehen"

Nächster Versuch:

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

Jetzt bekommt meine Funktion AddNewLocation () immer eine BodyData=null- auch wenn der Aufruf den Body sendet.

Schließlich habe ich alle 3 Parameter optional eingestellt:

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

Arbeite nicht:

Optionaler Parameter BodyDatawird von nicht unterstützt FormatterParameterBinding.

Warum möchte ich eine Lösung mit optionalen Parametern? Mein Controller übernimmt nur das "Hinzufügen eines neuen Standorts" über einen POST.

Ich möchte bei falschen Daten meine eigenen Ausnahmen oder Fehlermeldungen senden. Auch wenn der Anruf fehlende Werte hat. In diesem Fall möchte ich in der Lage sein, eine Ausnahme auszulösen oder Standardeinstellungen anhand meines Codes festzulegen.

Oliver Apel
quelle

Antworten:

174

/v1/location/1234Wie Sie sich vorstellen können, ist es für eine Web-API schwierig, bei einer eingehenden Anfrage wie automatisch herauszufinden, ob der Wert des Segments, das '1234' entspricht, mit appidund nicht mit '1234' zusammenhängt deviceid.

Ich denke, Sie sollten Ihre Routenvorlage so ändern, dass sie aussieht, [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]und dann die analysieren deiveOrAppid, um den Typ der ID herauszufinden.

Außerdem müssen Sie die Segmente in der Routenvorlage selbst optional machen, da sonst die Segmente als erforderlich betrachtet werden. Beachten Sie das ?Zeichen in diesem Fall. Beispielsweise: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]

Kiran Challa
quelle
55
?In der Routenvorlage habe ich gesucht. +1
Kal_Torak
4
Ich würde nicht sagen, dass "deviceOrAppId" die beste Designwahl ist. Ich denke, die API sollte per Definition immer wissen, was sie erhalten wird, wenn dies überhaupt möglich ist.
Niels Brinch
12
Nur zur Information - Wenn wir einen Parameter in der Aktion uri using ?Zeichen als optional markieren, müssen wir den Parametern in der Methodensignatur Standardwerte bereitstellen, z. B. MyMethod (string name = "someDefaultValue", int? Id = null).
RBT
@RBT du da echtes MVP, ich war dort für eine Minute ratlos. Danke dir!
sm
1
Cool. Ich bin froh, dass es dir geholfen hat @sm Ich habe meinen Kommentar in eine Antwort für eine bessere Sichtbarkeit umgewandelt, da er hilfreich erscheint. Es wird ein Add-On zu Kirans Post sein.
RBT
45

Weitere Informationen: Wenn Sie eine Routenbeschränkung verwenden möchten , stellen Sie sich vor, Sie möchten erzwingen, dass der Parameter den Datentyp int hat. Dann müssen Sie diese Syntax verwenden:

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

Die ? Zeichen werden immer vor den letzten gesetzt } Zeichen

Weitere Informationen finden Sie unter: Optionale URI-Parameter und Standardwerte

Tiago Ferreira
quelle
18

Meinen Kommentar in eine Antwort umwandeln, um die Antwort von @Kiran Chala zu ergänzen, da sie für das Publikum hilfreich erscheint.

Wenn wir einen Parameter in der Aktion uri using ?Zeichen als optional markieren, müssen wir den Parametern in der Methodensignatur Standardwerte wie folgt geben:

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

RBT
quelle
Ich wollte das gleiche kommentieren.
Jnr