asp.net-web-api
OData con Asp.net Web API
Ricerca…
Installa i pacchetti OData
Dal menu Strumenti, selezionare NuGet Package Manager> Console Gestione pacchetti. Nella finestra della console di Package Manager, digitare:
Install-Package Microsoft.AspNet.Odata
Questo comando installa i pacchetti OData NuGet più recenti.
Abilita Entity Framework
Per questo tutorial, utilizzeremo il codice Entity Framework (EF) First per creare il database back-end.
Web API OData non richiede EF. Utilizzare qualsiasi livello di accesso ai dati che possa convertire le entità del database in modelli.
Innanzitutto, installa il pacchetto NuGet per EF. Dal menu Strumenti , selezionare NuGet Package Manager > Console Gestione pacchetti . Nella finestra della console di Package Manager, digitare:
Install-Package EntityFramework
Aprire il file Web.config e aggiungere la seguente sezione all'interno dell'elemento di configurazione , dopo l'elemento configSections .
<configuration>
<configSections>
<!-- ... -->
</configSections>
<!-- Add this: -->
<connectionStrings>
<add name="ProductsContext" connectionString="Data Source=(localdb)\v11.0;
Initial Catalog=ProductsContext; Integrated Security=True; MultipleActiveResultSets=True;
AttachDbFilename=|DataDirectory|ProductsContext.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
Questa impostazione aggiunge una stringa di connessione per un database LocalDB. Questo database verrà utilizzato quando si esegue l'app localmente.
Quindi, aggiungi una classe denominata ProductsContext alla cartella Modelli:
using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}
Nel costruttore, "name = ProductsContext" fornisce il nome della stringa di connessione.
Configura l'endpoint OData
Apri il file App_Start / WebApiConfig.cs. Aggiungi le seguenti affermazioni usando :
using ProductService.Models;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
Quindi aggiungere il seguente codice al metodo 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());
}
}
Questo codice fa due cose:
- Crea un Entity Data Model (EDM).
- Aggiunge un percorso.
Un EDM è un modello astratto dei dati. L'EDM viene utilizzato per creare il documento dei metadati del servizio. La classe ODataConventionModelBuilder crea un EDM utilizzando le convenzioni di denominazione predefinite. Questo approccio richiede il codice minimo. Se si desidera un maggiore controllo sull'EDM , è possibile utilizzare la classe ODataModelBuilder per creare l'EDM aggiungendo proprietà, chiavi e proprietà di navigazione in modo esplicito.
Una rotta indica all'API Web come indirizzare le richieste HTTP all'endpoint. Per creare una route OData v4, chiamare il metodo di estensione MapODataServiceRoute .
Se l'applicazione ha più endpoint OData, creare un percorso separato per ciascuno. Assegnare a ogni percorso un nome e un prefisso univoci.
Aggiungi il controller OData
Un controller è una classe che gestisce le richieste HTTP. Crei un controller separato per ogni entità impostata nel tuo servizio OData. In questo tutorial, creerai un controller, per l'entità Product.
In Esplora soluzioni, fare clic con il pulsante destro del mouse sulla cartella Controller e selezionare Aggiungi > Classe . Assegna un nome alla classe ProductsController.
La versione di questo tutorial per OData v3 utilizza lo scaffold Add Controller. Attualmente, non esiste un'impalcatura per OData v4.
Sostituire il codice boilerplate in ProductsController.cs con quanto segue.
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);
}
}
}
Il controller utilizza la classe ProductsContext per accedere al database utilizzando EF. Si noti che il controller sovrascrive il metodo Dispose per eliminare ProductsContext .
Questo è il punto di partenza per il controller. Successivamente, aggiungeremo metodi per tutte le operazioni CRUD.
Esecuzione di CRUD sul set di entità
Interrogazione del set di entità
Aggiungere i seguenti metodi a 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);
}
La versione senza parametri del metodo Get restituisce l'intera raccolta Prodotti. Il metodo Get con un parametro chiave cerca un prodotto tramite la sua chiave (in questo caso, la proprietà Id).
L'attributo [EnableQuery] consente ai client di modificare la query, utilizzando opzioni di query quali $ filter, $ sort e $ page. Per ulteriori informazioni, vedere Supporto delle opzioni di query OData .
Aggiunta di una entità al set di entità
Per consentire ai client di aggiungere un nuovo prodotto al database, aggiungere il seguente metodo a ProductsController .
public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
Aggiornamento di un'entità
OData supporta due semantiche diverse per l'aggiornamento di un'entità, PATCH e PUT.
- PATCH esegue un aggiornamento parziale. Il client specifica solo le proprietà da aggiornare.
- PUT sostituisce l'intera entità.
Lo svantaggio di PUT è che il client deve inviare valori per tutte le proprietà nell'entità, inclusi i valori che non cambiano. Le specifiche OData indicano che PATCH è preferito.
In ogni caso, ecco il codice per entrambi i metodi PATCH e 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);
}
Nel caso di PATCH, il controller usa il tipo Delta <T> per tracciare le modifiche.
Eliminazione di un'entità
Per consentire ai client di eliminare un prodotto dal database, aggiungere il seguente metodo a 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);
}