ASP.NET Web API 2.2 Kullanarak OData v4'teki Eylemler ve İşlevler

tarafından Mike Wasson

OData'da eylemler ve işlevler, varlıklarda CRUD işlemleri olarak kolayca tanımlanmayan sunucu tarafı davranışları eklemenin bir yoludur. Bu öğreticide, Web API 2.2 kullanarak bir OData v4 uç noktasına nasıl eylem ve işlev ekleneceği gösterilmektedir. Öğretici, ASP.NET Web API 2 Kullanarak OData v4 Uç Noktası Oluşturma öğreticisini temel almaktadır

Öğreticide kullanılan yazılım sürümleri

  • Web API 2.2
  • OData v4
  • Visual Studio 2013 (Visual Studio 2017'i buradan indirin)
  • .NET 4.5

Öğretici sürümleri

OData Sürüm 3 için bkz. ASP.NET Web API 2'deki OData Eylemleri.

Eylemler ve işlevler arasındaki fark, eylemlerin yan etkileri olabileceği ve işlevlerin olmamasıdır. Hem eylemler hem de işlevler veri döndürebilir. Eylemler için bazı kullanımlar şunlardır:

  • Karmaşık işlemler.
  • Aynı anda birkaç varlığı işlemek.
  • Bir varlığın yalnızca belirli özellikleri için güncelleştirmelere izin verme.
  • Varlık niteliğinde olmayan veriler gönderiliyor.

İşlevler, doğrudan bir varlığa veya koleksiyona karşılık gelmeyen bilgileri döndürmekte kullanışlıdır.

Bir eylem (veya işlev) tek bir varlığı veya koleksiyonu hedefleyebilir. OData terminolojisinde bağlama budur. Hizmette statik işlemler olarak adlandırılan "ilişkisiz" eylemlere/işlevlere de sahip olabilirsiniz.

Örnek: Eylem Ekleme

Şimdi bir ürünü derecelendirecek bir eylem tanımlayalım.

Uyarı

Bu öğretici, ASP.NET Web API 2 Kullanarak OData v4 Uç Noktası Oluşturma öğreticisini temel almaktadır

İlk olarak derecelendirmeleri temsil eden bir ProductRating model ekleyin.

namespace ProductService.Models
{
    public class ProductRating
    {
        public int ID { get; set; }
        public int Rating { get; set; }
        public int ProductID { get; set; }
        public virtual Product Product { get; set; }  
    }
}

Ayrıca, EF'in veritabanında bir Derecelendirmeler tablosu oluşturması için sınıfına bir ProductsContext ekleyin.

public class ProductsContext : DbContext
{
    public ProductsContext() 
            : base("name=ProductsContext")
    {
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Supplier> Suppliers { get; set; }
    // New code:
    public DbSet<ProductRating> Ratings { get; set; }
}

Eylemi EDM'ye Ekle

WebApiConfig.cs aşağıdaki kodu ekleyin:

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");

// New code:
builder.Namespace = "ProductService";
builder.EntityType<Product>()
    .Action("Rate")
    .Parameter<int>("Rating");

EntityTypeConfiguration.Action yöntemi, varlık veri modeline (EDM) bir eylem ekler. Parameter yöntemi, eylem için yazılan bir parametre belirtir.

Bu kod, EDM için ad alanını da ayarlar. Ad alanı önemlidir çünkü eylem için URI, tam eylem adını içerir.

http://localhost/Products(1)/ProductService.Rate

Uyarı

Tipik bir IIS yapılandırmasında, bu URL'deki nokta IIS'nin 404 hatasını döndürmesine neden olur. Web.Config dosyanıza aşağıdaki bölümü ekleyerek bu sorunu çözebilirsiniz:

<system.webServer>
    <handlers>
      <clear/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" 
          verb="*" type="System.Web.Handlers.TransferRequestHandler" 
          preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

Eylem için Denetleyici Yöntemi Ekleme

"Derecelendirme" eylemini etkinleştirmek için aşağıdaki yöntemi ProductsController öğesine ekleyin.

[HttpPost]
public async Task<IHttpActionResult> Rate([FromODataUri] int key, ODataActionParameters parameters)
{
    if (!ModelState.IsValid)
    {
        return BadRequest();
    }

    int rating = (int)parameters["Rating"];
    db.Ratings.Add(new ProductRating
    {
        ProductID = key,
        Rating = rating
    });

    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateException e)
    {
        if (!ProductExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return StatusCode(HttpStatusCode.NoContent);
}

Yöntem adının eylem adıyla eşleştiğinden dikkat edin. [HttpPost] özniteliği yöntemin bir HTTP POST yöntemi olduğunu belirtir.

eylemi çağırmak için istemci aşağıdaki gibi bir HTTP POST isteği gönderir:

POST http://localhost/Products(1)/ProductService.Rate HTTP/1.1
Content-Type: application/json
Content-Length: 12

{"Rating":5}

"Rate" eylemi, Ürün örnekleriyle ilişkilidir, bu nedenle eylemin URI'si, varlık URI'sine eklenen tam eylem adını içerir. (EDM ad alanını "ProductService" olarak ayarladığımızdan, tam eylem adının "ProductService.Rate" olduğunu hatırlayın.)

İsteğin gövdesi, eylem parametrelerini JSON yükü olarak içerir. Web API'si, JSON yükünü otomatik olarak bir ODataActionParameters nesnesine dönüştürür ve bu yalnızca parametre değerlerinin sözlüğüdür. Denetleyici yönteminizdeki parametrelere erişmek için bu sözlüğü kullanın.

İstemci eylem parametrelerini yanlış biçimde gönderirse , ModelState.IsValid değeri false olur. Denetleyici yönteminizde bu bayrağı denetleyin ve IsValid yanlışsa bir hata döndürin.

if (!ModelState.IsValid)
{
    return BadRequest();
}

Örnek: İşlev Ekleme

Şimdi en pahalı ürünü döndüren bir OData işlevi ekleyelim. Daha önce olduğu gibi, ilk adım işlevi EDM'ye eklemektir. WebApiConfig.cs aşağıdaki kodu ekleyin.

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
builder.EntitySet<Supplier>("Suppliers");

// New code:
builder.Namespace = "ProductService";
builder.EntityType<Product>().Collection
    .Function("MostExpensive")
    .Returns<double>();

Bu durumda işlev, tek tek Product örnekleri yerine Products koleksiyonuna bağlıdır. İstemciler get isteği göndererek işlevi çağırır:

GET http://localhost:38479/Products/ProductService.MostExpensive

Bu işlevin denetleyici yöntemi aşağıdadır:

public class ProductsController : ODataController
{
    [HttpGet]
    public IHttpActionResult MostExpensive()
    {
        var product = db.Products.Max(x => x.Price);
        return Ok(product);
    }

    // Other controller methods not shown.
}

Yöntem adının işlev adıyla eşleştiğinden dikkat edin. [HttpGet] özniteliği yöntemin bir HTTP GET yöntemi olduğunu belirtir.

HTTP yanıtı aşağıdadır:

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
OData-Version: 4.0
Date: Sat, 28 Jun 2014 00:44:07 GMT
Content-Length: 85

{
  "@odata.context":"http://localhost:38479/$metadata#Edm.Decimal","value":50.00
}

Örnek: İlişkisiz İşlev Ekleme

Önceki örnek, bir koleksiyona bağlı bir işlevdi. Bu sonraki örnekte, ilişkisiz bir işlev oluşturacağız. İlişkisiz işlevler, hizmette statik işlemler olarak adlandırılır. Bu örnekteki işlev, belirli bir posta kodu için satış vergisini döndürür.

WebApiConfig dosyasında, işlevini EDM'ye ekleyin:

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");

// New code:
builder.Function("GetSalesTaxRate")
    .Returns<double>()
    .Parameter<int>("PostalCode");

İşlevi varlık türü veya koleksiyonu yerine doğrudan ODataModelBuilder üzerinde çağırdığımıza dikkat edin. Bu, model oluşturucuya işlevin bağlanmamış olduğunu bildirir.

İşlevi uygulayan denetleyici yöntemi aşağıdadır:

[HttpGet]
[ODataRoute("GetSalesTaxRate(PostalCode={postalCode})")]
public IHttpActionResult GetSalesTaxRate([FromODataUri] int postalCode)
{
    double rate = 5.6;  // Use a fake number for the sample.
    return Ok(rate);
}

Bu yöntemi hangi Web API denetleyicisine yerleştirdiğiniz önemli değildir. bunu içine ProductsControllerkoyabilir veya ayrı bir denetleyici tanımlayabilirsiniz. [ODataRoute] özniteliği işlevi için URI şablonunu tanımlar.

Örnek istemci isteği aşağıda verilmiştir:

GET http://localhost:38479/GetSalesTaxRate(PostalCode=10) HTTP/1.1

HTTP yanıtı:

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
OData-Version: 4.0
Date: Sat, 28 Jun 2014 01:05:32 GMT
Content-Length: 82

{
  "@odata.context":"http://localhost:38479/$metadata#Edm.Double","value":5.6
}