Parameter Opsional di Perutean Atribut Web Api

90

Saya ingin menangani POST dari Panggilan API berikut:

/v1/location/deviceid/appid

Parameter tambahan berasal dari Post-Body.

Ini semua bekerja dengan baik untuk saya. Sekarang saya ingin memperpanjang kode saya dengan mengizinkan "deviceid" dan / atau "appid" dan / atau BodyData menjadi null:

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

3 URL ini harus ditanggapi dengan rute yang sama.

Pendekatan pertama saya (diperlukan BodyData):

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

Ini tidak berfungsi dan mengembalikan kesalahan kompilasi:

"Parameter opsional harus di akhir"

Percobaan berikutnya:

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

Sekarang fungsi saya AddNewLocation () selalu menjadi BodyData=null- bahkan jika panggilan mengirim Body.

Akhirnya saya mengatur semua 3 Parameter opsional:

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

Jangan bekerja:

Parameter opsional BodyDatatidak didukung oleh FormatterParameterBinding.

Mengapa saya menginginkan solusi dengan Parameter opsional? Kontroler Saya hanya menangani "penambahan Lokasi baru" melalui POST.

Saya ingin mengirim data yang salah pengecualian saya sendiri atau pesan kesalahan. Bahkan jika panggilan tersebut memiliki nilai yang hilang. Dalam hal ini saya ingin dapat memutuskan untuk melempar pengecualian atau Mengatur Default dengan kode saya.

Oliver Apel
sumber

Jawaban:

177

Untuk permintaan yang masuk seperti /v1/location/1234, seperti yang dapat Anda bayangkan, akan sulit bagi API Web untuk secara otomatis mengetahui apakah nilai segmen yang sesuai dengan '1234' terkait dengan appiddan tidak terkait deviceid.

Saya pikir Anda harus mengubah template rute Anda menjadi seperti [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]dan kemudian mengurai deiveOrAppiduntuk mengetahui jenis id.

Anda juga perlu membuat segmen di template rute itu sendiri opsional, jika tidak, segmen dianggap diperlukan. Perhatikan ?karakter dalam kasus ini. Sebagai contoh: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]

Kiran Challa
sumber
56
?di dalam template rute inilah yang saya cari. +1
Kal_Torak
4
Saya tidak akan mengatakan bahwa "deviceOrAppId" adalah pilihan desain terbaik. Saya pikir API harus selalu mengetahui secara definisi apa yang akan diterimanya jika memungkinkan.
Niels Brinch
14
Hanya untuk informasi - Ketika kita menandai parameter sebagai opsional dalam tindakan uri menggunakan ?karakter maka kita harus memberikan nilai default ke parameter di tanda tangan metode misalnya MyMethod (nama string = "someDefaultValue", int? Id = null).
RBT
@RBT Anda da MVP asli, saya bingung di sana sebentar. Terima kasih!
sm
1
Keren. Senang bisa membantu Anda @sm. Saya telah mengubah komentar saya menjadi jawaban untuk visibilitas yang lebih baik karena tampaknya membantu. Ini akan menjadi tambahan pada postingan Kiran.
RBT
45

Info lain: Jika Anda ingin menggunakan Route Constraint , bayangkan Anda ingin memaksa parameter itu memiliki tipe data int , maka Anda perlu menggunakan sintaks ini:

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

Itu ? Karakter yang dimasukkan selalu sebelum yang terakhir } karakter

Untuk informasi selengkapnya, lihat: Parameter URI Opsional dan Nilai Default

Tiago Ferreira
sumber
18

Mengubah komentar saya menjadi jawaban untuk melengkapi jawaban @Kiran Chala karena tampaknya membantu para penonton-

Ketika kita menandai parameter sebagai opsional dalam tindakan uri menggunakan ?karakter maka kita harus memberikan nilai default ke parameter di tanda tangan metode seperti yang ditunjukkan di bawah ini:

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

NSP
sumber
Saya akan berkomentar sama.
Yoh