Neden FromBody ve FromUri'yi belirtmeliyiz?


157

ASP.NET Web API'sinde FromBodyve FromUriözniteliklerine neden ihtiyaç duyulur?

Öznitelikleri kullanma ve kullanmama arasındaki farklar nelerdir?


11
[FromBody] ek açıklamasının ne zaman yararlı olabileceğine dair bir ipucu vermek için: Örneğin, URL'de kodlanan parametreler olarak kullanıcı adı / şifre gibi statik kimlik bilgilerini göndermek kötü bir uygulamadır. SSL şifrelemesi, üçüncü bir tarafın URL içindeki parametrelere okuma erişimi kazanmasını engelleyebilse de, bu kimlik bilgileri tarayıcı günlüklerinde ve eşitlerinde saklanabileceğinden, bu hala kesinlikle istenmemektedir. Böyle bir durumda, bir yüksek sokulması, HTTP iletisinin gövdesi içindeki bir parametrenin depolanmasını zorlamak için, [FromBody] ek açıklama kullanabilir
Chris

Yanıtlar:


193

ASP.NET Web API bir denetleyicide bir yöntem çağırdığında, parametreler için değer ayarlaması gerekir; bu işlem parametre bağlama olarak adlandırılır .

Web API varsayılan olarak parametreleri bağlamak için aşağıdaki kuralları kullanır:

  • Parametre "basit" bir türse , Web API değeri URI'den almaya çalışır . Basit türler arasında .NET ilkel türleri (int, bool, double vb.), Ayrıca TimeSpan, DateTime, Guid, ondalık ve dize ve ayrıca bir dizeden dönüştürebilen bir tür dönüştürücüsü olan herhangi bir tür bulunur.

  • Karmaşık türler için Web API , ortam türü biçimlendirici kullanarak ileti gövdesindeki değeri okumaya çalışır .

Bu nedenle, yukarıdaki varsayılan davranışı geçersiz kılmak ve Web API'sını URI'den karmaşık bir tür okumaya zorlamak istiyorsanız, [FromUri]niteliği parametreye ekleyin . Web API'sini istek gövdesinden basit bir tür okumaya zorlamak için,[FromBody] niteliği parametreye .

Bu nedenle, sorunuzu yanıtlamak için Web API'sındaki [FromBody]ve [FromUri]özniteliklerinin ihtiyacı, gerekirse, yukarıda açıklanan varsayılan davranışı geçersiz kılmaktır. Bir denetleyici yöntemi için her iki özelliği de kullanabileceğinizi, ancak burada gösterildiği gibi yalnızca farklı parametreler için kullanabileceğinizi unutmayın .

Google "web api parametre bağlama" yaparsanız web üzerinde çok daha fazla bilgi vardır .


2
@ user3510527: Varsayılan davranışı izlediğiniz sürece, istemiyorsanız bu nitelikleri kullanmanız gerekmez. Varsayılan davranışı değiştirmek istiyorsanız, bunları kullanmanız gerekir.
djikay

1
varsayılan davranışını yapıyorsa, neden ovveride etmemiz gerekiyor ve bu özellikten bahsedersek ne gibi faydalar elde edeceğiz?
Rajneesh

1
@ user3510527 Geçersiz kılmanıza gerek yok . Sadece varsayılan davranışı kullanabilirsiniz. Birinin geçersiz kılmak isteyebileceği örneklerden biri, isteğin gövdesinde basit bir tamsayı sağlamak isteyip istemediğidir, çünkü varsayılan olarak bunu URI'de bulmayı bekler. Temel olarak, isterseniz varsayılan davranışı bırakabilirsiniz veya geçersiz kılabilirsiniz, sadece sahip olduğunuz bir seçenektir. Karışıklıkların ne olduğunu anlamıyorum.
djikay

sadece form özniteliğini kullanırsak iç çalışma sürecini bilmek istiyorum, bu yüzden doğrudan değeri alacak ve herhangi bir uri veya formbody kontrol değil ...
Rajneesh

7
Bir vb JustGetItgibi birden çok özellik eklemek için aynı amaca hizmet eden denilen bir özellik yapabilir miyim merak ediyorum[FromBody, FromQuery]
The Muffin Man

93

Varsayılan davranış:

  1. Parametre ise ilkel tipi ( int, bool, double, ...), Web API çalışır gelen değeri elde etmek URI HTTP isteğinin.

  2. İçin karmaşık türleri (örneğin kendi nesne: Person), Web API çalışır değeri okumak için vücudun HTTP isteğinin.

Yani, eğer varsa:

  • URI'de ilkel bir tür veya
  • vücutta karmaşık bir tip

... hiçbir özellik eklemenize gerek yoktur (ne ne [FromBody]de[FromUri] ).

Eğer bir varsa Ama, ilkel tip içinde vücutta , ardından eklemek zorunda[FromBody] senin WebAPI denetleyici yönteminde ilkel tip parametre önünde. (Çünkü WebAPI, HTTP isteğinin URI'sinde ilkel türleri arar.)

Eğer bir varsa Veya, karmaşık türü sizin de URI , ardından eklemek gerekir[FromUri] . (Varsayılan olarak, WebAPI, HTTP isteğinin gövdesinde varsayılan olarak karmaşık türler arar.)

İlkel tipler:

public class UsersController : ApiController
{
    // api/users
    public HttpResponseMessage Post([FromBody]int id)
    {

    }
    // api/users/id
    public HttpResponseMessage Post(int id)
    {

    }       
}

Karmaşık tipler:

public class UsersController : ApiController
{       
    // api/users
    public HttpResponseMessage Post(User user)
    {

    }

    // api/users/user
    public HttpResponseMessage Post([FromUri]User user)
    {

    }       
}

HTTP isteğinizde yalnızca bir parametre gönderdiğiniz sürece çalışır . Birden çok gönderirken , tüm parametrelerinize sahip olan özel bir model oluşturmanız gerekir:

public class MyModel
{
    public string MyProperty { get; set; }
    public string MyProperty2 { get; set; }
}

[Route("search")]
[HttpPost]
public async Task<dynamic> Search([FromBody] MyModel model)
{
    // model.MyProperty;
    // model.MyProperty2;
}

Microsoft'un ASP.NET Web API'sındaki parametre bağlamaya ilişkin belgelerinden :

Bir parametrede [FromBody] varsa, Web API bir biçimlendirici seçmek için Content-Type üstbilgisini kullanır. Bu örnekte, içerik türü "application / json" ve istek gövdesi ham JSON dizesidir (JSON nesnesi değil). Mesaj gövdesinden en fazla bir parametrenin okunmasına izin verilir.

Bu çalışmalı:

public HttpResponseMessage Post([FromBody] string name) { ... }

Bu işe yaramaz:

// Caution: This won't work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

Bu kuralın nedeni, istek gövdesinin yalnızca bir kez okunabilen arabelleğe alınmamış bir akışta depolanabilmesidir.


5
"En fazla bir parametre mesaj gövdesinden okumak için izin verilir" özellikle yararlı bilgiler oldu
Ryan

15

Yukarıdaki cevaplara ek olarak ..

[FromUri], sorgu dizgisinden parametre iletmek yerine karmaşık türleri uri parametrelerinden bağlamak için de kullanılabilir

Örn ..

public class GeoPoint
{
    public double Latitude { get; set; } 
    public double Longitude { get; set; }
}

[RoutePrefix("api/Values")]
public ValuesController : ApiController
{
    [Route("{Latitude}/{Longitude}")]
    public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}

Gibi çağrılabilir:

http://localhost/api/values/47.678558/-122.130989

12

Bir parametrede [FromBody] varsa, Web API bir biçimlendirici seçmek için Content-Type üstbilgisini kullanır. Bu örnekte, içerik türü "application / json" ve istek gövdesi ham JSON dizesidir (JSON nesnesi değil).

Mesaj gövdesinden en fazla bir parametrenin okunmasına izin verilir. Yani bu işe yaramayacak:

 // Caution: Will not work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

Bu kuralın nedeni, istek gövdesinin yalnızca bir kez okunabilen arabelleğe alınmamış bir akışta depolanabilmesidir.

Daha fazla bilgi için lütfen web sitesini ziyaret edin: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

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.