在ASP.NET Web API中使用OData的Action和Function
本篇体验OData的Action和Function功能。上下文信息参考"ASP.NET Web API基于OData的增删改查,以及处理实体间关系"。在本文之前,我存在的疑惑包括:
● 为什么需要OData的Action和Function功能?
● Action和Function之间有什么区别?
● 如何设置OData的的Action和Function功能?这中间有哪些惯例呢?
为某个Product添加Action
如果我们希望通过http://localhost:54714/odata/Products(1)/SomeActionName来实现在某个Product基础上,为Product的关联表ProductRating添加一条数据,该如何做到呢?
首先创建产品评论的一个模型:
public class ProductRating
{
public int ID { get; set; }
public int Rating { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
}
把模型添加到上下文中:
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<ProductRating> Ratings { get; set; }
}
添加迁移并更新数据库:
Add-Migration "AddProductRating" -StartUpProjectName ProductService -ProjectName ProductService
Update-Database -StartUpProjectName ProductService -ProjectName ProductService
现在,需要在WebApiConfig.cs中的Register方法中,为Product的EDM添加一个Action。
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "ProductService"; builder.EntitySet<Product>("Products");//创建EntityDataModel(EDM)
builder.EntitySet<Supplier>("Suppliers"); //http://localhost/Products(1)/ProductService.Rate 注意需要在Web.config中添加配置,因为在IIS上不允许带点,否则会返回404
builder.EntityType<Product>()
.Action("Rate")//给EDM添加一个Action
.Parameter<int>("Rating"); //Rating作为参数在前后端传递 config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model:builder.GetEdmModel());
以上,
● 通过builder.Namespace定义了Action的命名空间为ProductService
● 通过Action方法给Product这个EDM定义了Rate这个Action
● 通过Parameter<T>方法定义了参数
这意味着:
● 我们发出的请求格式大致是:http://localhost:54714/odata/Products(1)/ProductService.Rate
● API的action方法中,action名称是Rate,可以从前端接受一个名称为Rating的键值
可问题还有:
● 前端如何把Rating这个参数传递出去呢?
● 后端又如何接受这个Rating参数呢?
来看后端控制器部分的action,在ProductsController中添加如下:
//这里的action名称Rate必须和EDM定义的时候保持一致
[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 ex)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
} return StatusCode(HttpStatusCode.NoContent); }
可见,后端是通过ODataActionParameters来接受前端传来的变量Rating。
现在前端可以试着发出请求了:
POST http://localhost:54714/odata/Products(1)/ProductService.Rate
Body {"Rating":5}
我们把Rating变量放在了Body中,以json传递给后端。
可是,返回结果是: 404 Not Found
这是因为,IIS还不接受类似ProductService.Rate这样的写法,在Web.config添加如下配置:
<system.webServer>
<handlers>
...
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="/odata/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
重新请求,返回:204 No Content
为Product集合添加Action
如果想为Products集合添加如下方法发出如下请求:http://localhost:54714/odata/Products/ProductService.MostExpensive
首先还是配置EDM:
builder.EntityType<Product>().Collection
.Function("MostExpensive")
.Returns<double>();
在ProductsController中添加如下Action:
[HttpGet]
public IHttpActionResult MostExpensive()
{
var product = db.Products.Max(x => x.Price);
return Ok(product);
}
前端请求:
GET http://localhost:54714/odata/Products/ProductService.MostExpensive
返回:
{
"@odata.context": "http://localhost:54714/odata/$metadata#Edm.Decimal",
"value": 18.2
}
和EDM模型无关,添加Function
当我们需要添加一个与EDM 模型无关的方法时候,就使用Function。
首先在WebApi.config中配置如下:
builder.Function("GetSalesTaxRate")
.Returns<double>()
.Parameter<int>("PostalCode");
在某个Controller中添加如下:
[HttpGet]
[ODataRoute("GetSalesTaxRate(PostalCode={postalCode})")]
public IHttpActionResult GetSalesTaxRate([FromODataUri] int postalCode)
{
double rate = 5.8;
return Ok(rate);
}
以上,ODataRoute设定路由规则。前端发出如下请求:
GET http://localhost:54714/odata/GetSalesTaxRate(PostalCode=10)
返回:
{
"@odata.context": "http://localhost:54714/odata/$metadata#Edm.Double",
"value": 5.8
}
总结:当需要针对某个EDM模型或EDM模型集合进行CRUD以外的操作,甚至涉及多个模型的操作使用Action,但添加和EDM模型无关的操作,使用Function。
在ASP.NET Web API中使用OData的Action和Function的更多相关文章
- ASP.NET Web API中使用OData
在ASP.NET Web API中使用OData 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在ASP.NET Web API中,对于CRUD(creat ...
- 在ASP.NET Web API中使用OData
http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...
- [翻译]在ASP.NET Web API中通过OData支持查询和分页
OData可以通过形如http://localhost/Products?$orderby=Name这样的QueryString传递查询条件.排序等.你可以在任何Web API Controller中 ...
- 在ASP.NET Web API中使用OData的Containment
通常情况下,一个OData的EDM(Entity Data Model)在配置的时候定义了,才可以被查询或执行各种操作.比如如下: builder.EntitySet<SomeModel> ...
- 在ASP.NET Web API中使用OData的单例模式
从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样.实现方式大致需要两步: 1.在需要实现单例模式的导航属性上加上[Singleton] ...
- ASP.NET Web API中的Controller
虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...
- ASP.NET Web API 中的异常处理(转载)
转载地址:ASP.NET Web API 中的异常处理
- 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化
谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...
- Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...
随机推荐
- Workflow规则收藏
豆瓣电影 查看电影评分等详细信息 查看图片EXIF 图铃机器人 快递查询 翻译 手机号码归属地 音乐视频下载 获取附近的免费WIFI
- mysql innobackupex 备份及恢复
----------------------------------全量备份恢复-------------------------------------1.生成一个完整的备份 innobackupe ...
- centos7环境配置haproxy实现mysql数据库和redis代理服务器
centos7环境配置haproxy实现mysql数据库代理 我们通常会碰到这样的业务场景: b主机和c数据库在同一个内网,a主机不能直接访问c数据库,我们可以通过在b主机上搭建代理让a访问c数据库, ...
- InteliJ IDEA 简单使用:配置项目所需jdk
1:配置项目所需jdk: File->Project Structure 弹出如下界面: 首先选中SDKs,会出现下图界面:点击“+”标志弹出Add New SDK 然后选择JDK,会弹出路径框 ...
- 驱动程序vmci.sys版本不正确。请尝试重新安装 VMware
今天在测试一台服务器,安装在虚拟机里面,但是发现在安装后,重启了一下电脑,出现了这个错误: 无法获取 vmci 驱动程序版本: 句柄无效.驱动程序 vmci.sys 版本不正确.请尝试重新安装 VMw ...
- C/C++有效对齐值的确定
先来看看什么是对齐.现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型 ...
- 【LOJ】#2887. 「APIO2015」雅加达的摩天楼 Jakarta Skyscrapers
题解 事实上是个分块暴力 就是跳跃长度大于\(\sqrt{n}\)的狗最多有\(\sqrt{n}\)个位置 剩下跳跃长度小于\(\sqrt{n}\)的暴力记录 也就是两个\(dis\)数组 \(dis ...
- 【洛谷】P4198 楼房重建
题解 我们转而维护每个点的斜率,显然一个楼房能被看见它就是一个前缀最大值,斜率比较为了节约精度可以用向量替代 我们每个区间维护被看到的楼房的个数,和楼房的最大值,叶子节点在有楼房时,值为1 那么考虑合 ...
- gym 101986
A - Secret of Chocolate Poles 队友写的. 好像水水的. //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pr ...
- Java字符串跟ASCII码互转
1.由于项目中遇到,在服务器端起的jar包程序,给前台发消息后,前段收到的消息出现乱码情况,所以采取在后才发消息前先把消息字符串转成ASCII码再发往前台,前台采取在收到后台消息先把ASCII码转成字 ...