ASP.NET Web API'sında isteğe bağlı sorgu dizesi parametreleri


212

Aşağıdaki WebAPI yöntemini uygulamak gerekir:

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX

Tüm sorgu dizesi parametreleri boş olabilir. Yani, arayan 0 ila 5 parametrenin tümünü belirtebilir.

In MVC4 beta ben aşağıdakileri yapmak için kullanılan:

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RC artık böyle davranmıyor. 5'ten az parametre belirtirseniz, bir 404deyimle yanıt verir :

'Kitaplar' denetleyicisinde istekle eşleşen bir eylem bulunamadı.

URL yönlendirmesinde isteğe bağlı parametreyi belirtmeden, eskisi gibi davranmasını sağlamak için doğru yöntem imzası nedir?


[httpget] 'ı eyleme geçirin.
user960567

2
Tüm parametreleri ayarlarsam yöntem çağrılır; ayrıca Getotomatik olarak HTTP GETyönteme bağlı olarak başlar ...
frapontillo

Web api yönlendirme bu şekilde çalışır, asp.net/web-api/overview/web-api-routing-and-actions/…
user960567

4
Evet. Nasıl çalıştığını biliyorum. BU özel koşullar altında çalışmasını sağlayamıyorum.
frapontillo

Bu nasıl derlendi? string?geçerli bir tür değil. Sen beyan edemez stringbir başvuru türü olduğundan null türü olarak.
EkoostikMartin

Yanıtlar:


307

Bu sorun, MVC4'ün düzenli sürümünde giderilmiştir. Şimdi şunları yapabilirsiniz:

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

ve her şey kutudan çıkar.


Burada null değerini varsayılan olarak kullanabilir miyim? Örneğin: string author = null?
Boris Zinchenko

2
Evet, nullbir kabul edilir sabiti ifadesi bir nedenle ve geçerli varsayılan değer .
JDawg

Acaba neden burada belirtildiği gibi isteğe bağlı parametreler için varsayılan değerlerden bahsetmek zorundayız . C # 'daki herhangi bir tür her zaman varsayılan değere sahiptir, bu nedenle yönlendirme çalışma zamanı, URI'den almadıysa, türün varsayılan değerini almış olabilir. Bunun arkasındaki teknik neden nedir? Bunun model bağlayıcıyla bir ilgisi olduğuna eminim.
RBT

@RBT Böylece rota eşleştirilebilir
James Westgate

Tarih parametrelerini kullanıyordum ve sadece nullable olarak ayarladım, çalışma değildi. Bu yüzden nulllable ve set null değerlerini varsayılan değer olarak ayarlamalıyım ve buna göre sunucu tarafı doğrulamasını kullanmalı ve hata mesajlarını geri döndürmeliyim. İşe yaradı.
Saldırı H.

85

Vijay'in önerdiği gibi tek bir model olarak birden fazla parametre geçirmek mümkündür. FromUri parametre özniteliğini kullandığınızda bu GET için çalışır. Bu, WebAPI'ye modeli sorgu parametrelerinden doldurmasını bildirir.

Sonuç, tek bir parametreyle daha temiz bir denetleyici eylemidir. Daha fazla bilgi için bkz. Http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

public class BooksController : ApiController
  {
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks([FromUri]BookQuery query)
    {
      // ...
    }
  }

  public class BookQuery
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string SomethingElse { get; set; }
    public DateTime? Date { get; set; }
  }

Özellikler çakışmadığı sürece birden fazla parametreyi bile destekler.

// GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
public string GetFindBooks([FromUri]BookQuery query, [FromUri]Paging paging)
{
  // ...
}

public class Paging
{
  public string Sort { get; set; }
  public int Skip { get; set; }
  public int Take { get; set; }
}

Güncelleme :
Değerlerin isteğe bağlı olduğundan emin olmak için, model özellikleri için referans türleri veya nullables (örn. İnt?) Kullandığınızdan emin olun.


4
Evet, ancak yalnızca [FromUri] dekoratörü isteğe bağlı parametreleri desteklemiyor gibi görünüyor.
John Meyer

6
@JohnMeyer [FromUri] kullanarak doğru soruyu doğrudan yanıtlamıyorsunuz. Temel olarak, bu modelleri Uri'den gelen değerlerle doldurun diyor. Model özelliklerinin, isteğe bağlı olmalarını destekleyebilmeleri için boş veya referans türünde olması gerekir. Ek bilgi eklendi.
Andrew C

@AndrewC - Değerlerin isteğe bağlı olduğundan emin olmak için nullables'ı ne zaman / neden kullanmanız gerektiği hakkında ayrıntılı bilgi verebilir misiniz? Değerleri boş bırakmazsanız (ex, özellik için int Skip) ve belirtilen bu özellik için sorgu parametresi yoksa, API Denetleyicisi yöntemi yine de isteği başarıyla eşleştirir ve Skipdeğeri bu tür için varsayılan değer olur, veya bu durumda 0
Clark

2
@Clark - Sıfırlanabilir bir tür kullanmadan, kullanıcının bir değer sağlamadığını ve başlatılmamış tür değerini (int için 0) alıp almadığını veya kullanıcı 0'ı belirtip belirtmediğini bilemezsiniz. Nullable kullanarak kullanıcının tanımsız bıraktığından emin olursunuz bu nedenle varsayılanı denetleyici eylemine güvenle uygulayabilirsiniz. Yukarıdaki örnekten Take'ye bakarsanız, Take için 0 aldıysa eylem ne yapmalıdır? Kullanıcı 0 kayıt istemek anlamına mı geliyordu yoksa belirtmedi mi ve bu nedenle tüm kayıtları almalısınız. Genellikle bir değer türünün (int, bool, vb.) İsteğe bağlı olmasını istiyorsanız, boş değer olmalıdır.
Andrew C

70

Aşağıdaki gibi tüm parametreler için başlangıç ​​varsayılan değerlerini kullanın

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

1
Bu doğru prosedürdür, ancak bir kere: DateTimenull değeri yoktur. Zaten kullanmaya çalıştım DateTime?, ancak HTTP isteğimin yalnızca bazı parametrelerini ayarladıysam MVC isteği verilen yönteme eşlemiyor.
frapontillo

DateTime.Parse () işlevini kullanarak tarihi bir dize olarak iletebilir ve denetleyici işlevinizin içinde ayrıştırabilirsiniz.
Muhammed Amin

1
@MuhammadAmin, DateTimebir değil olabilecek veri türü. nullTür parametresine değer atayamayacağınız için kodunuz derlenmemelidir DateTime. Belki de bunu DateTime?varsayılan değer olarak değiştirmelisiniz veya farklı bir değer kullanmalısınız DateTime.Now.
Ivaylo Slavov

1
@IvayloSlavov DateTime.Now derleme zaman sabiti değil, bu yüzden varsayılan parametre olarak atanamıyor.
GiriB

@GiriB, haklısın. Datetime.Nowvarsayılan parametre başlatmasında kullanılamaz, düzeltilmiş duruyorum.
Ivaylo Slavov

1

birden fazla parametre iletmek istiyorsanız, birden fazla parametre iletmek yerine model oluşturabilirsiniz.

herhangi bir parametreyi geçmek istemiyorsanız, o zaman içinde de atlayabilirsiniz ve kodunuz düzgün ve temiz görünecektir.


1
Bu yalnızca istek gövdesindeki POST parametreleri için geçerlidir - url'deki parametreler yine de bağımsız olarak bağımsız değişken olarak başvurulabilir.
Nathan

1

Bildirilmeyen parametreler için varsayılan değerler sağlanamaz ' optional'

 Function GetFindBooks(id As Integer, ByVal pid As Integer, Optional sort As String = "DESC", Optional limit As Integer = 99)

Sizin WebApiConfig

 config.Routes.MapHttpRoute( _
          name:="books", _
          routeTemplate:="api/{controller}/{action}/{id}/{pid}/{sort}/{limit}", _
          defaults:=New With {.id = RouteParameter.Optional, .pid = RouteParameter.Optional, .sort = UrlParameter.Optional, .limit = UrlParameter.Optional} _
      )

8
Aslında yapabilirler. VB.NET değil C # kullanıyorum.
frapontillo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.