Tworzenie punktu końcowego OData w wersji 4 przy użyciu internetowego interfejsu API ASP.NET
Protokół Open Data Protocol (OData) to protokół dostępu do danych dla sieci Web. OData zapewnia jednolity sposób wykonywania zapytań o zestawy danych i manipulowania nimi za pomocą operacji CRUD (tworzenie, odczytywanie, aktualizowanie i usuwanie).
ASP.NET internetowy interfejs API obsługuje protokół w wersji 3 i 4. Możesz nawet mieć punkt końcowy w wersji 4, który działa obok punktu końcowego w wersji 3.
W tym samouczku pokazano, jak utworzyć punkt końcowy OData w wersji 4, który obsługuje operacje CRUD.
Wersje oprogramowania używane w samouczku
- Internetowy interfejs API 5.2
- OData 4
- Visual Studio 2017 (pobierz program Visual Studio 2017 tutaj)
- Entity Framework 6
- .NET 4.7.2
Wersje samouczka
Aby uzyskać informacje o danych OData w wersji 3, zobacz Creating an OData v3 Endpoint (Tworzenie punktu końcowego OData w wersji 3).
Tworzenie projektu programu Visual Studio
W programie Visual Studio z menu Plik wybierz pozycję Nowy>projekt.
Rozwiń węzeł Installed Visual C#Web (Zainstalowano program>Visual C#>Web) i wybierz szablon ASP.NET Web Application (.NET Framework). Nadaj projektowi nazwę "ProductService".
Wybierz przycisk OK.
Wybierz szablon Pusty . W obszarze Dodaj foldery i podstawowe odwołania dla: wybierz pozycję Internetowy interfejs API. Wybierz przycisk OK.
Instalowanie pakietów OData
Z menu Narzędzia wybierz pozycję Konsola menedżera pakietów NuGetPackage Manager>. W oknie Konsola menedżera pakietów wpisz:
Install-Package Microsoft.AspNet.Odata
To polecenie instaluje najnowsze pakiety NuGet OData.
Dodawanie klasy modelu
Model to obiekt reprezentujący jednostkę danych w aplikacji.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Models. Z menu kontekstowego wybierz pozycję Dodaj>klasę.
Uwaga
Zgodnie z konwencją klasy modeli są umieszczane w folderze Modele, ale nie trzeba przestrzegać tej konwencji we własnych projektach.
Nadaj klasie Product
nazwę . W pliku Product.cs zastąp standardowy kod następującym kodem:
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; }
}
}
Właściwość Id
jest kluczem jednostki. Klienci mogą wykonywać zapytania o jednostki według klucza. Na przykład aby uzyskać produkt o identyfikatorze 5, identyfikator URI to /Products(5)
. Właściwość Id
będzie również kluczem podstawowym w bazie danych zaplecza.
Włączanie programu Entity Framework
Na potrzeby tego samouczka użyjemy programu Entity Framework (EF) Code First do utworzenia bazy danych zaplecza.
Uwaga
Dane OData internetowego interfejsu API nie wymagają platformy EF. Użyj dowolnej warstwy dostępu do danych, która może tłumaczyć jednostki bazy danych na modele.
Najpierw zainstaluj pakiet NuGet dla programu EF. Z menu Narzędzia wybierz pozycję Konsola menedżera pakietów NuGetPackage Manager>. W oknie Konsola menedżera pakietów wpisz:
Install-Package EntityFramework
Otwórz plik Web.config i dodaj następującą sekcję wewnątrz elementu konfiguracji po elemecie 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>
To ustawienie dodaje parametry połączenia dla bazy danych LocalDB. Ta baza danych będzie używana podczas lokalnego uruchamiania aplikacji.
Następnie dodaj klasę o nazwie ProductsContext
do folderu Models:
using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}
W konstruktorze "name=ProductsContext"
podaje nazwę parametrów połączenia.
Konfigurowanie punktu końcowego OData
Otwórz plik App_Start/WebApiConfig.cs. Dodaj następujące instrukcje using :
using ProductService.Models;
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;
Następnie dodaj następujący kod do metody 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());
}
}
Ten kod wykonuje dwie czynności:
- Tworzy model danych jednostki (EDM).
- Dodaje trasę.
Model EDM jest abstrakcyjnym modelem danych. Moduł EDM służy do tworzenia dokumentu metadanych usługi. Klasa ODataConventionModelBuilder tworzy EDM przy użyciu domyślnych konwencji nazewnictwa. Takie podejście wymaga najmniejszego kodu. Jeśli chcesz mieć większą kontrolę nad modułem EDM, możesz użyć klasy ODataModelBuilder do utworzenia modułu EDM, dodając jawnie właściwości, klucze i właściwości nawigacji.
Trasa informuje internetowy interfejs API, jak kierować żądania HTTP do punktu końcowego. Aby utworzyć trasę OData w wersji 4, wywołaj metodę rozszerzenia MapODataServiceRoute .
Jeśli aplikacja ma wiele punktów końcowych OData, utwórz oddzielną trasę dla każdego z nich. Nadaj każdej trasie unikatową nazwę i prefiks trasy.
Dodawanie kontrolera OData
Kontroler jest klasą, która obsługuje żądania HTTP. Należy utworzyć oddzielny kontroler dla każdego zestawu jednostek w usłudze OData. W tym samouczku utworzysz jeden kontroler dla Product
jednostki.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj>klasę. Nadaj klasie ProductsController
nazwę .
Uwaga
Wersja tego samouczka dla usługi OData w wersji 3 używa szkieletu Dodaj kontroler . Obecnie nie ma szkieletu dla protokołu OData w wersji 4.
Zastąp standardowy kod w pliku ProductsController.cs następującym kodem.
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);
}
}
}
Kontroler używa klasy do uzyskiwania ProductsContext
dostępu do bazy danych przy użyciu programu EF. Zwróć uwagę, że kontroler zastępuje metodę Dispose w celu usunięcia obiektu ProductsContext.
Jest to punkt wyjścia dla kontrolera. Następnie dodamy metody dla wszystkich operacji CRUD.
Wykonywanie zapytań względem zestawu jednostek
Dodaj następujące metody do ProductsController
metody .
[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);
}
Wersja bez parametrów Get
metody zwraca całą kolekcję Products. Metoda Get
z parametrem klucza wyszukuje produkt według jego klucza (w tym przypadku Id
właściwość ).
Atrybut [EnableQuery] umożliwia klientom modyfikowanie zapytania przy użyciu opcji zapytania, takich jak $filter, $sort i $page. Aby uzyskać więcej informacji, zobacz Obsługa opcji zapytania OData.
Dodawanie jednostki do zestawu jednostek
Aby umożliwić klientom dodawanie nowego produktu do bazy danych, dodaj następującą metodę do ProductsController
metody .
public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
Aktualizowanie jednostki
Protokół OData obsługuje dwie różne semantyki do aktualizowania jednostki, PATCH i PUT.
- Patch wykonuje częściową aktualizację. Klient określa tylko właściwości do zaktualizowania.
- FUNKCJA PUT zastępuje całą jednostkę.
Wadą funkcji PUT jest to, że klient musi wysyłać wartości dla wszystkich właściwości w jednostce, w tym wartości, które nie zmieniają się. Specyfikacja OData wskazuje, że opcja PATCH jest preferowana.
W każdym przypadku oto kod dla metod PATCH i 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);
}
W przypadku poprawki kontroler używa typu delta<T> do śledzenia zmian.
Usuwanie jednostki
Aby umożliwić klientom usunięcie produktu z bazy danych, dodaj następującą metodę do ProductsController
metody .
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);
}