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 eylemlerin ve işlevlerin nasıl 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'de OData Eylemleri.

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

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

İşlevler, doğrudan bir varlığa veya koleksiyona karşılık gelen bilgileri döndürmek için 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.

Not

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'nin ProductsContext veritabanında bir Derecelendirme tablosu oluşturması için sınıfına bir DbSet 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 ekleme

WebApiConfig.cs dosyasına 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. Eylem için URI tam eylem adını içerdiğinden ad alanı önemlidir:

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

Not

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

"Hız" eylemini etkinleştirmek için aşağıdaki yöntemi öğesine ProductsControllerekleyin:

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

"Oran" eylemi Ürün örneklerine bağlıdır, bu nedenle eylemin URI'si varlık URI'sine eklenen tam eylem adıdır. (EDM ad alanını "ProductService" olarak ayarladığımız için 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 da 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ürür.

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 dosyasına 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şlevini ç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ı şu şekildedir:

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şturucusunun işlevin ilişkisiz 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şlev için URI şablonunu tanımlar.

Aşağıda örnek bir istemci isteği 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
}