本篇体验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的更多相关文章

  1. ASP.NET Web API中使用OData

    在ASP.NET Web API中使用OData 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在ASP.NET Web API中,对于CRUD(creat ...

  2. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  3. [翻译]在ASP.NET Web API中通过OData支持查询和分页

    OData可以通过形如http://localhost/Products?$orderby=Name这样的QueryString传递查询条件.排序等.你可以在任何Web API Controller中 ...

  4. 在ASP.NET Web API中使用OData的Containment

    通常情况下,一个OData的EDM(Entity Data Model)在配置的时候定义了,才可以被查询或执行各种操作.比如如下: builder.EntitySet<SomeModel> ...

  5. 在ASP.NET Web API中使用OData的单例模式

    从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样.实现方式大致需要两步: 1.在需要实现单例模式的导航属性上加上[Singleton] ...

  6. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  7. ASP.NET Web API 中的异常处理(转载)

    转载地址:ASP.NET Web API 中的异常处理

  8. 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化

    谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...

  9. 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 ...

随机推荐

  1. 初步认识mitmproxy(一)

    在windows机器上,经常用的最多的是fiddler工具,很强大,图形化界面,使用方便.简单:在mac上,Charles 类似fiddler工具,同样是易于操作的图形化界面,同样都是通过代理的方式实 ...

  2. 解决C/C++语言中全局变量重复定义的问题

    前言 今天,在整理自己的代码的时候,考虑到我写的代码从一至终都是在一个cpp文件里面.于是,想把自己的代码中的各个模块分离开来,以便更好地阅读和管理. 遇到的问题 我的做法是: 宏定义.结构体定义.函 ...

  3. asp.net后台获取前台页面大小

    前台代码如下:<input type="hidden" runat="server" value="0" id="txBod ...

  4. 去除Android APP里面的广告

    如何去除Android游戏软件中的广告:很多时候,我们下载好一款Andriod游戏软件,却被游戏软件中的广告弄的很烦.不停跳动的广告让人觉得非常不爽,而且在玩游戏的时候,还有可能点击到广告,中断游戏. ...

  5. 4.自定义数据《jquery实战》

    4.4 元素中的存储自定义数据 data([key],[value]) 在元素上存放数据,返回jQuery对象. key (String) 存储的数据名. key,value (String,Any) ...

  6. rabbitMQ的安装(Windows下)

    在公司接触到这一块,信息中间件的使用,在公司没有时间了解的更加深入,只是在简单的使用,这里将深入学习一番. 参考:http://blog.csdn.net/lu1005287365/article/d ...

  7. 013 jquery中关于表格行的增删问题

    1.程序 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...

  8. ubuntun 18.04 desktop安装jupyter-notebook

    在ubuntu18.04要安装jupyter-notebook,当然前提是先安装python,然后按如下步骤安装jupyter-notebook,现在记录如下: 1.sudo apt-get upda ...

  9. 001.Parted工具使用

    一 Parted简介 1.1 parted和fdisk 通常使用较多的磁盘管理工具为fdisk,但由于磁盘越来越廉价,且磁盘空间越来越大,而fdisk工具分区存在大小限制,只能划分小于2T的磁盘.因此 ...

  10. 前端Hack之XSS攻击个人学习笔记

    简单概述 **        此篇系本人两周来学习XSS的一份个人总结,实质上应该是一份笔记,方便自己日后重新回来复习,文中涉及到的文章我都会在末尾尽可能地添加上,此次总结是我在学习过程中所写,如有任 ...