[转]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教程(六) 安全与身份认证 摘要: 在实际的项目应 ...
随机推荐
- WebBrowser控件支持WebSocket
修改html页面,在Header标签中添加如下标签: <meta http-equiv="X-UA-Compatible"content="IE=edge" ...
- 【OCP-12c】CUUG 071题库考试原题及答案解析(21)
3.choose three View the Exhibit and examine the description of SALES and PROMOTIONS tables. You want ...
- 前端切图要选择png和jpg呢?
今天特意验证了一下: 切完图分别保存png24.png8和jpg60.jpg80(60和80表示保存图片时品质选择)后, 然后再压缩图片,压缩图片地址:https://tinypng.com/ 图片直 ...
- lucene3.0_IndexSearcher排序
系列汇总: lucene3.0_基础使用及注意事项汇总 IndexSearcher排序 本文主要讲解: 1.IndexSearcher中和排序相关的方法及sort类.SortField类(api级别) ...
- Make ISO安装ArchLinux加Cinnamon
Arch安装一直对大家对普通用户来說一直很难.国外大神为Arch安装进行了优化提供了更方便的安装方式 官网:http://www.evolutionlinux.com/ 以下爲个人理解,供大家参考. ...
- x == (x = y) 不等于 (x = y) == x ?
简评:不瞒你说,我现在数数都是从 0 开始数的,整数是 1024. 有这么一个 Java 程序: class Quirky { public static void main(String[] arg ...
- 阿里云 下载的 apache 证书 转换为 pcks8 证书
第一步: 百度 搜索 rsa 转 pcks8 将 .key 文件 转换成 pcks8.key . 第二部: 将 chain.crt 的 内容 复制到 public.crt 下方.. 新的 publi ...
- js字符串去重
js字符串去重: 1. 去掉字符串前后所有空格: function Trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } ...
- JS正则表达式端口号,IP地址
端口号:65535 正则:/^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6 ...
- bzoj4998: 星球联盟(link-cut-tree)
题面 bzoj 题解 bzoj2959: 长跑的弱化版 产生了环就并查集维护一下 Code #include<bits/stdc++.h> #define LL long long #de ...