[转]Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务
本文转自:http://www.cnblogs.com/fzrain/p/3923727.html
前言
很久没更新了,之前有很多事情,所以拖了很久,非常抱歉。好了,废话不多说,下面开始正题。本篇仍然使用上一季的的项目背景(系列地址http://www.cnblogs.com/fzrain/p/3490137.html)来演示OData服务,因此我们可以直接使用之前建好的数据访问层。但是不是说一定要看到之前的所有内容,我们只是借用数据库访问层,对于数据库的模型构建移步(使用Entity Framework Code First构建数据库模型)。
有了数据访问的基础,我们可以开始构建OData服务了。
第一步:创建空的Web Api项目

打开项目的解决方案,新建web项目,选择空的web api项目(如上图所示),记得选择.Net Framework 4.5。建好项目之后需要添加对“EntityFramework”和“Learning.Data”(我们的数据访问层)的引用。
第二步:添加OData引用
在默认的情况下,Web Api是无法支持OData的,因此我们需要添加对“Microsoft.ASP.NET Web API 2.1 OData”的引用——打开NuGet如下图所示:

第三步:配置OData路由
打开“App_Start”文件夹中系统帮我们创建的“WebApiConfig”类,在这里有一个Register方法并注册路由规则。我们需要配置的OData也是写在这里,代码如下:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务 // Web API 路由
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapODataRoute("elearningOData", "OData", GenerateEdmModel());
}
private static IEdmModel GenerateEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Course>("Courses");
builder.EntitySet<Enrollment>("Enrollments");
builder.EntitySet<Subject>("Subjects");
builder.EntitySet<Tutor>("Tutors"); return builder.GetEdmModel();
}
}

虽然我们只是使用OData服务,但我并没有移除默认的配置因为这两种路由规则是可以共存的。
上面为我们的OData服务配置了路由规则以及实体数据模型(EDM)
EDM主要是定义数据类型、导航属性和方法来适应OData的格式。有2种方式来定义EDM,第一种是基于公约的方式,我们将使用“ODataConventionModelBuilder”类,另一种则是使用“ODataModelBuilder”。
在这里我们将使用“ODataConventionModelBuilder ”因为它会根据我们定义的导航属性来生成关联集合的链接。相比来说写的代码比较少。如果你想在关联集合间有更多的控制,那么你可以使用“ODataModelBuilder”。
我们在builder对象中添加了4个不同的实体,注意:字符串参数“Courses”定义的实体集合名字必须与Controller的名字保持一致,也就是说我们的controller的名字必须是“CoursesController”。
“MapODataRoute”是一个扩展方法,当我们添加对OData引用时就可以使用了。它主要为OData服务来定义路由规则的:第一个参数指定一个名字,这个名字客户端是不会用到的;第二个参数是指对应OData终结点的URI前缀(在我们的案列中访问Courses资源的URI就应该是:http://hostname/odata/Courses)。你可以在同一个应用程序中拥有多个OData终结点,只需要调用“MapODataRoute”方法指定不同的前缀就行了。
第四步:添加第一个只读的OData控制器
现在我们创建一个Web Api控制器来处理OData URI类似“/odata/Courses”的HTTP请求。右击controller文件夹->新增->选择“空的API控制器”模板并命名“CoursesController”。
创建好之后,首先将我们的基类改成“System.Web.Http.OData.EntitySetController”。这个泛型基类需要2个参数:第一个指映射到这个controller对应的实体类型;第二个参数是指这个实体主键的类型,下面上代码:

public class CoursesController : EntitySetController<Course, int>
{
LearningContext ctx = new LearningContext(); [Queryable(PageSize = 10)]
public override IQueryable<Course> Get()
{
return ctx.Courses.AsQueryable();
} protected override Course GetEntityByKey(int key)
{
return ctx.Courses.Find(key);
}
}

“EntitySetController”类定义了很多抽象和可重写的方法来更新和查询实体,因此你会发现你可以重写很多的方法例如:Get(),GetEntityByKey(),CreateEntrty(),PatchEntity(),UpdateEntity(),etc…
正如我前面提到的,我们将创建一个只读的控制器,这就意味着我们只实现读取的操作,解释一下上面代码的实现:
1.重写Get()方法并附上[Queryable]特性,这意味着我们允许客户端发送HTTP的Get到我们的终结点并在URI参数值支持filter,order by,pagination的操作。Queryable特性是一个action过滤器,主要转换和校验查询的URI及相应参数,当客户端查询将花费很多时间或者大量数据时候这个特性将会有意想不到的作用(举个例子:设置PageSize属性,这样一次性只会给客户端返回10条数据)
2.重写GetEntityByKey(int key)方法将支持客户端发送HTTP访问单个资源,形式类似于“/odata/Courses(5)”。注:这里的key代表对应实体的主键。
第五步:测试Courses控制器
现在我们开始测试我们的controller,对于所有的请求我们都将accept header指定为“application/json”,因此我们将获得轻量JSON数据,你也可以去指定accept header为“application/json;odata=verbose”或者“application/atom+xml”来查看结果。
我们演示一下场景:
1.$filter:我们查询所有时长超过4小时的课程:发送Get请求http://{hostname}/OData/Courses?$filter=Duration gt 4
2.$orderby, $take:我们需要根据课程名排序并获取前5条记录:发送Get请求http://{hostname}/OData/Courses?$orderby=Name&$top=5
3.$select:我们仅需要获取Name和Duration字段的值:发送Get请求http://{hostname}/OData/Courses?$select=Name,Duration
4.$expand:我们需要获取每个课程对应的主题和讲师并根据课程名倒序排列:发送Get请求http://{hostname}/OData/Courses?$expand=CourseTutor,CourseSubject&$orderby=Name desc
通过刚刚4个例子我们可以看到在我们的返回结果中包含了UserName和Password这两个字段,但个信息是没必要给客户端的。,

十分幸运的是我们只需要去配置一下EDM就可以在返回结果中不包含这两个字段了,具体做法在WebApiConfig类中的GenerateEdmModel()方法里加入如下代码:

private static IEdmModel GenerateEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Course>("Courses");
builder.EntitySet<Enrollment>("Enrollments");
builder.EntitySet<Subject>("Subjects");
builder.EntitySet<Tutor>("Tutors");
var tutorsEntitySet = builder.EntitySet<Tutor>("Tutors"); tutorsEntitySet.EntityType.Ignore(s => s.UserName);
tutorsEntitySet.EntityType.Ignore(s => s.Password); return builder.GetEdmModel();
}

[转]Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务的更多相关文章
- Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务
前言 很久没更新了,之前有很多事情,所以拖了很久,非常抱歉.好了,废话不多说,下面开始正题.本篇仍然使用上一季的的项目背景(系列地址http://www.cnblogs.com/fzrain/p/34 ...
- Web Api系列教程第2季(OData篇)(一)——OData简介和一个小应用
第一季的链接以及系列导航:http://www.cnblogs.com/fzrain/p/3490137.html 在这里,首先要感谢Taiseer Joudeh不断的为我们带来最新的技术分享,楼主对 ...
- ASP.NET Web API系列教程目录
ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Start ...
- ASP.NET Web API系列教程(目录)(转)
注:微软随ASP.NET MVC 4一起还发布了一个框架,叫做ASP.NET Web API.这是一个用来在.NET平台上建立HTTP服务的Web API框架,是微软的又一项令人振奋的技术.目前,国内 ...
- [转]ASP.NET Web API系列教程(目录)
本文转自:http://www.cnblogs.com/r01cn/archive/2012/11/11/2765432.html 注:微软随ASP.NET MVC 4一起还发布了一个框架,叫做ASP ...
- Web攻防系列教程之文件上传攻防解析(转载)
Web攻防系列教程之文件上传攻防解析: 文件上传是WEB应用很常见的一种功能,本身是一项正常的业务需求,不存在什么问题.但如果在上传时没有对文件进行正确处理,则很可能会发生安全问题.本文将对文件上传的 ...
- 源码学习系列之SpringBoot自动配置(篇二)
源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...
- SpringBoot系列之profles配置多环境(篇二)
SpringBoot系列之profles配置多环境(篇二) 继续上篇博客SpringBoot系列之profles配置多环境(篇一)之后,继续写一篇博客进行补充 写Spring项目时,在测试环境是一套数 ...
- 【转】ASP.NET WEB API系列教程
from: 西瓜小强 http://www.cnblogs.com/risk/category/406988.html ASP.NET Web API教程(六) 安全与身份认证 摘要: 在实际的项目应 ...
随机推荐
- 浅谈TCP通讯
基于Tcp协议的Socket通讯类似于B/S架构,面向连接,但不同的是服务器端可以向客户端主动推送消息. 使用Tcp协议通讯需要具备以下几个条件: (1).建立一个套接字(Socket) (2).绑定 ...
- Mysql 优化与测试
由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 : --> 点击这里 以下的测试数据根据环境的不同所耗费的时间有所不同,例如我在腾讯云上的测试 ...
- 【12c OCP】CUUG OCP认证071考试原题解析(34)
34.choose two View the Exhibit and examine the structure of the PRODUCT_INFORMATION and INVENTORIES ...
- [agc006f] Blackout 神题
Description 给你一个NN行NN列的网格,第ii行第jj列的格子用(i,j)(i,j)表示 一开始的时候有MM个格子被涂成黑色,其他的格子都是白色,具体一点,涂成黑色的格子为(a1,b1 ...
- 【转载】hadoop之failed task任务和killed task任务
failed task可理解为自杀,也就是task本身出了问题而自杀:killed task可理解为是他杀,也就是jobtracker认为这个任务的执行是多余的,所以把任务直接杀掉.起初用hadoop ...
- robot framework踩坑记录
一.报错:FAIL : 'Return' is a reserved keyword. 给Retrun加上中括号即可 二.报错:True != true 三.报错 /Library/Python/2. ...
- robot framework学习笔记之七—连接mysql数据库
1.安装Database-Library 输入命令:pip install robotframework_databaselibrary 2.添加Database的Library 3.实例 * ...
- 如何查看mysql 默认端口号和修改端口号
http://blog.itpub.net/26148431/viewspace-1466379/ 1,登录mysql 2,使用命令show global variables like 'port'; ...
- HTML5语义化标签总结
1.语义化标签总结 基础布局标签 <header></header> <nav></nav> <main></main> < ...
- 在Eclipse之中调试FastDFS-storage
FDFS版本为5.03 1.首先在eclipse之中创建一个C/C++工程,取名为FastDFS_v5.03 2.将FastDFS源码解压后拷贝到新创建的工程目录下,然后在ecipse之中刷新下工程就 ...