在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 ...
随机推荐
- 【密码学】RSA算法过程-求解密钥
1.密钥的计算获取过程 密钥的计算过程为:首先选择两个质数p和q,令n=p*q. 令k=ϕ(n)=(p−1)(q−1),原理见2的分析 选择任意整数d,保证其与k互质 取整数e,使得[de]k=[1] ...
- 查询orcale运行的SQL语句记录
select c.* from V$SQL c where c.MODULE='ukhis.exe' order by last_active_time desc
- Using NHibernate with SQLite
The most convenient method to add NHibernate and SQLite for C# project is using NuGet. You can check ...
- nginx log 错误502 upstream sent too big header while reading response header from upstream
cookies的值超出了范围我是说 看看了一下日志 错误502 upstream sent too big header while reading response header from upst ...
- MVC 6 电商网站开发实战
[原创] ASP.NET 5系列教程 (六): 在 MVC6 中创建 Web API 标签: Web API MVC6 创建web API | 博主:powertoolsteam ASP.NE ...
- linux 检测远程端口是否打开
linux 检测远程端口是否打开 检测远程端口是否打开 常用telnet 110.101.101.101 80方式测试远程主机端口是否打开. 除此之外还可以使用: 方法1.nmap i ...
- WinSCP命令行操作
WinSCP命令行操作 WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端.同时支持SCP协议.它的主要功能就是在本地与远程计算机间安全的复制文件. 直接在cmd下输入 ...
- 【Android Studio】为Android Studio设置HTTP代理
[Android Studio]为Android Studio设置HTTP代理 大陆的墙很厚很高,初次安装Android Studio下载SDK等必定失败,设置代理方法如下: 1. 到androi ...
- 006.LVM快照
一 快照介绍 快照就是将当时的系统信息记录下来,就好像照相一样,未来若有任何资料变动了,则原始资料会被移动到快照区,没有被改动的区域则由快照区与档案系统共享. 二 快照原理 当建立快照区时,LVM会预 ...
- 003.FTP客户端连接
一 命令行连接 注意: 1:命令行连接不支持目录下载,使用mget也只会将目录下文件下载,不会下载目录本身. 2:命令行连接不支持断点续传. ftp [服务端IP] -help #获取帮助 - -mg ...