Membuat Titik Akhir OData v4 Menggunakan API Web ASP.NET
Open Data Protocol (OData) adalah protokol akses data untuk web. OData menyediakan cara yang seragam untuk mengkueri dan memanipulasi himpunan data melalui operasi CRUD (membuat, membaca, memperbarui, dan menghapus).
ASP.NET Web API mendukung protokol v3 dan v4. Anda bahkan dapat memiliki titik akhir v4 yang berjalan berdampingan dengan titik akhir v3.
Tutorial ini menunjukkan cara membuat titik akhir OData v4 yang mendukung operasi CRUD.
Versi perangkat lunak yang digunakan dalam tutorial
- WEB API 5.2
- OData v4
- Visual Studio 2017 (unduh Visual Studio 2017 di sini)
- Entity Framework 6
- .NET 4.7.2
Versi tutorial
Untuk OData Versi 3, lihat Membuat Titik Akhir OData v3.
Membuat Proyek Visual Studio
Di Visual Studio, dari menu File, pilihProyekBaru>.
PerluasVisual C#>Webyang Terinstal>, dan pilih templat Aplikasi Web ASP.NET (.NET Framework). Beri nama proyek "ProductService".
PilihOK.
Pilih templat Tugas kosong. Di bawah Tambahkan folder dan referensi inti untuk:, pilih WEB API. PilihOK.
Menginstal paket OData
Dari menu Alat, pilih Pengelola Paket NuGet>Konsol Pengelola Paket. Di jendela Konsol Pengelola Paket, ketik:
Install-Package Microsoft.AspNet.Odata
Perintah ini menginstal paket OData NuGet terbaru.
Menambahkan kelas model
Model adalah objek yang mewakili entitas data di aplikasi Anda.
Di Penjelajah Solusi, klik kanan folder Model. Dari menu konteks, pilih Tambahkan>Kelas.
Catatan
Berdasarkan konvensi, kelas model ditempatkan di folder Model, tetapi Anda tidak perlu mengikuti konvensi ini dalam proyek Anda sendiri.
Beri nama kelas Product
. Dalam file Product.cs, ganti kode boilerplate dengan yang berikut:
namespace ProductService.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
}
Properti Id
adalah kunci entitas. Klien dapat mengkueri entitas berdasarkan kunci. Misalnya, untuk mendapatkan produk dengan ID 5, URI adalah /Products(5)
. Properti Id
juga akan menjadi kunci utama dalam database back-end.
Aktifkan Kerangka Kerja Entitas
Untuk tutorial ini, kita akan menggunakan Kode Kerangka Kerja Entitas (EF) Terlebih Dahulu untuk membuat database back-end.
Catatan
OData API Web tidak memerlukan EF. Gunakan lapisan akses data apa pun yang dapat menerjemahkan entitas database ke dalam model.
Pertama, instal paket NuGet untuk EF. Dari menu Alat, pilih Pengelola Paket NuGet>Konsol Pengelola Paket. Di jendela Konsol Pengelola Paket, ketik:
Install-Package EntityFramework
Buka file Web.config, dan tambahkan bagian berikut di dalam elemen konfigurasi , setelah elemen configSections .
<configuration>
<configSections>
<!-- ... -->
</configSections>
<!-- Add this: -->
<connectionStrings>
<add name="ProductsContext" connectionString="Data Source=(localdb)\mssqllocaldb;
Initial Catalog=ProductsContext; Integrated Security=True; MultipleActiveResultSets=True;
AttachDbFilename=|DataDirectory|ProductsContext.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
Pengaturan ini menambahkan string koneksi untuk database LocalDB. Database ini akan digunakan saat Anda menjalankan aplikasi secara lokal.
Selanjutnya, tambahkan kelas bernama ProductsContext
ke folder Model:
using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}
Di konstruktor, "name=ProductsContext"
berikan nama string koneksi.
Mengonfigurasi titik akhir OData
Buka file App_Start/WebApiConfig.cs. Tambahkan pernyataan penggunaan berikut:
using ProductService.Models;
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;
Kemudian tambahkan kode berikut ke metode Register :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}
Kode ini melakukan dua hal:
- Membuat Model Data Entitas (EDM).
- Menambahkan rute.
EDM adalah model abstrak data. EDM digunakan untuk membuat dokumen metadata layanan. Kelas ODataConventionModelBuilder membuat EDM dengan menggunakan konvensi penamaan default. Pendekatan ini membutuhkan kode paling sedikit. Jika Anda ingin kontrol lebih besar atas EDM, Anda dapat menggunakan kelas ODataModelBuilder untuk membuat EDM dengan menambahkan properti, kunci, dan properti navigasi secara eksplisit.
Rute memberi tahu Web API cara merutekan permintaan HTTP ke titik akhir. Untuk membuat rute OData v4, panggil metode ekstensi MapODataServiceRoute .
Jika aplikasi Anda memiliki beberapa titik akhir OData, buat rute terpisah untuk masing-masing titik akhir. Beri setiap rute nama rute dan awalan yang unik.
Menambahkan pengontrol OData
Pengontrol adalah kelas yang menangani permintaan HTTP. Anda membuat pengontrol terpisah untuk setiap entitas yang diatur dalam layanan OData Anda. Dalam tutorial ini, Anda akan membuat satu pengontrol, untuk Product
entitas.
Di Penjelajah Solusi, klik kanan folder Pengontrol dan pilih Tambahkan>Kelas. Beri nama kelas ProductsController
.
Catatan
Versi tutorial ini untuk OData v3 menggunakan perancah Tambahkan Pengontrol . Saat ini, tidak ada perancah untuk OData v4.
Ganti kode boilerplate di ProductsController.cs dengan yang berikut ini.
using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
public class ProductsController : ODataController
{
ProductsContext db = new ProductsContext();
private bool ProductExists(int key)
{
return db.Products.Any(p => p.Id == key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
Pengontrol menggunakan ProductsContext
kelas untuk mengakses database menggunakan EF. Perhatikan bahwa pengontrol mengambil alih metode Buang untuk membuang ProductsContext.
Ini adalah titik awal untuk pengontrol. Selanjutnya, kita akan menambahkan metode untuk semua operasi CRUD.
Mengkueri kumpulan entitas
Tambahkan metode berikut ke ProductsController
.
[EnableQuery]
public IQueryable<Product> Get()
{
return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
IQueryable<Product> result = db.Products.Where(p => p.Id == key);
return SingleResult.Create(result);
}
Versi metode tanpa Get
parameter mengembalikan seluruh koleksi Produk. Metode Get
dengan parameter kunci mencari produk dengan kuncinya (dalam hal ini, Id
properti ).
Atribut [EnableQuery] memungkinkan klien mengubah kueri, dengan menggunakan opsi kueri seperti $filter, $sort, dan $page. Untuk informasi selengkapnya, lihat Mendukung Opsi Kueri OData.
Menambahkan entitas ke set entitas
Untuk memungkinkan klien menambahkan produk baru ke database, tambahkan metode berikut ke ProductsController
.
public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
Memperbarui entitas
OData mendukung dua semantik yang berbeda untuk memperbarui entitas, PATCH dan PUT.
- PATCH melakukan pembaruan parsial. Klien hanya menentukan properti yang akan diperbarui.
- PUT menggantikan seluruh entitas.
Kerugian put adalah klien harus mengirim nilai untuk semua properti dalam entitas, termasuk nilai yang tidak berubah. Spesifikasi OData menyatakan bahwa PATCH lebih disukai.
Bagaimanapun, berikut adalah kode untuk metode PATCH dan PUT:
public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.Products.FindAsync(key);
if (entity == null)
{
return NotFound();
}
product.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (key != update.Id)
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
Dalam kasus PATCH, pengontrol menggunakan jenis Delta<T> untuk melacak perubahan.
Menghapus entitas
Untuk memungkinkan klien menghapus produk dari database, tambahkan metode berikut ke ProductsController
.
public async Task<IHttpActionResult> Delete([FromODataUri] int key)
{
var product = await db.Products.FindAsync(key);
if (product == null)
{
return NotFound();
}
db.Products.Remove(product);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}