Create an OData v4 Endpoint Using ASP.NET Web API 2.2(使用ASP.NET Web API 2.2创建OData v4端点)

时间:2022-10-27 15:37:26

开放数据协议Open Data Protocol(OData)是web的一种数据存取协议,OData通过设置CRUD操作(Create创建。Read读取。Update更新,Delete删除)提供一种统一的方式来查询或者操作数据。

ASP.Net Web API同一时候支持该协议v3和v4版本号,你甚至能够在执行v4的端点(Endpoint)时执行v3的端点(Endpoint)。

本课程展示了怎样创建OData v4的端点(Endpoint)来提供CRUD操作。

教程里使用的软件版本号

教程版本号

点击Creating
an OData v3 Endpoint
可跳转至OData Version 3.

创建Visual Studioproject

打开Visual Studio,在File(文件)菜单中。选择New > Project(新建>项目)。

展开 Installed > Templates > Visual
C# > Web(已安装>模板>Visual
C#>Web)。选择ASP.NET
Web Application(ASP.NET Web应用程序)模板,将project名称命名为“ProductService”。

Create an OData v4 Endpoint Using ASP.NET Web API 2.2(使用ASP.NET Web API 2.2创建OData v4端点)

在New Project(新建项目)对话框里选择Empty(空模板)。在"Add
folders and core references..."(为下面对象加入目录和核心引用)。择Web API,然后点击OK(确定)。

Create an OData v4 Endpoint Using ASP.NET Web API 2.2(使用ASP.NET Web API 2.2创建OData v4端点)

安装OData包

在Tools(工具)菜单里。选择NuGet
Package Manager > Package
Manager Console(NuGet程序包管理>程序包管理器控制台)。在程序包管理器控制台视窗里输入:

Install-Package Microsoft.AspNet.Odata

该命令将会安装最新的OData NuGet包。

加入一个Model 类(模型类)

在你的应用程序里。一个Model(模型)就是一个展现数据实体的对象。

在Solution Explorer(解决方式资源管理器)里,右击名为Models的目录,在右键菜单里,选择Add > Class(加入>类)。

Create an OData v4 Endpoint Using ASP.NET Web API 2.2(使用ASP.NET Web API 2.2创建OData v4端点)

依照惯例。model classes(模型类)会被放入名为Models的目录里,只是在你project里你并不一定要遵循这种规则。

将该类命名为Product,在Product.cs文件中,使用下面代码替换样本代码。

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

Id 属性是这个实体的键。client能够依据键来查询实体。要查询并得到Id 是5的Product,它的资源路径便是/Products(5),在后台数据库里Id 也是主键。

启用实体框架

在本次教程里,我们将使用Entity Framework (EF) Code First来创建后台数据库。

Web API OData并不一定须要EF,你能够使用不论什么可将数据实体转换为models(模型)的数据訪问层。

首先,安装EF的NuGet包。在Tools(工具)菜单里。选择NuGet Package
Manager > Package
Manager Console(NuGet程序包管理>程序包管理器控制台)。

在程序包管理器控制台视窗里输入:

Install-Package EntityFramework

打开Web.config文件,将下面位于configuration 节点内。configSections节点后的部分加入至该文件里对应位置。

<configuration>
<configSections>
<!-- ... -->
</configSections> <span style="background-color: rgb(255, 255, 0);"><!-- Add this: --></span>
<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>

该设置里加入了一个链接LocalDB(本地数据库)的链接字符串。

当你在本地执行此程序时,本地数据库将被使用。

下一步。在Models目录里加入一个名为ProductsContext 的类。

using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}

在构造函数里,"name=ProductsContext"给出了连接字符串的名称。

配置OData Endpoint

打开文件App_Start/WebApiConfig.cs,加入下面引用语句。

using ProductService.Models;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;

然后加入下面代码至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());
}
}

这段代码做了两件事情

  • 创建Entity Data Model(EDM实体数据模型)
  • 添加一个Route(路由)

EDM是数据的抽象模型,EDM被用来创建服务的元数据文件。

ODataConventionModelBuilder使用默认的命名规则创建EDM。这样的方法须要少量的代码。假设你想很多其它支配EDM的话,你能够使用通过明白地加入属性、键和导航属性来创建EDM。

Route告诉了Web API应该如何路由Http请求至Endpoint(端点)中。你能够通过调用MapODataServiceRoute 扩展的方法来创建OData
v4 route(路由)。

假设你的程序里有多个OData Endpoint,你须要为它们分别创建一个route,且给它们不同的Route路由名称和前缀。

加入OData控制器

控制器是处理Http请求的类。你能够为每个OData服务的实体创建不同的控制器。

在本教程里,你将为Product 实体创建一个控制器。

在Solution Explorer(解决方式资源管理器)里,右击名为Controllers 的目录,在右键菜单里,选择Add > Class(加入>类)。将其命名为ProductsController。

在OData v3教程里我们使用了Add
Controller对话框,但眼下还没有OData v4版的。

在ProductsController.cs中用下面代码替换样本代码。

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);
}
}
}

控制器使用ProductsContext类通过EF来訪问数据库。注意,该控制器重写了Dispose 方法来释放ProductsContext。

这是控制的開始。下一步,我们将为全部的CRUD操作加入方法。

Querying the Entity Set 查询实体集

加入下面代码至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);
}

当中一个没有參数的Get 方法返回Product 的实体集合。而有一个參数的Get 方法则是通过Product的键来查找对应的Product(在这样的情况下。键就是Id属性)。

[EnableQuery]标签通过使用查询设置$filter,
$sort, $page 来改动查询。具体信息请点击Supporting
OData Query Options

Adding an Entity to the Entity Set 加入实体至实体集

为了使client能够加入新Product 至数据库中,我们加入例如以下方法至ProductsController。

public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}

Updating an Entity 更新实体

OData支持两种不同的语法来更新实体。PATCH 和PUT。

  • PATCH运行部分更新。client仅仅需指定须要更新的属性。
  • PUT 替换整个实体。

PUT 的不利之处是client必须发送实体全部属性的值,包含那些没有改变的值。OData
规范书
推荐使用PATCH。

无论如何。下面是PATCH和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);
}

在PATCH情况下,控制器使用Delta<T>来跟踪实体的改变。

Deleting an Entity 删除实体

为了能让client从数据库中删除实体,我们能够在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);
}

原文地址http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint