[转]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项目

image_thumb1

打开项目的解决方案,新建web项目,选择空的web api项目(如上图所示),记得选择.Net Framework 4.5。建好项目之后需要添加对“EntityFramework”和“Learning.Data”(我们的数据访问层)的引用。

第二步:添加OData引用

在默认的情况下,Web Api是无法支持OData的,因此我们需要添加对“Microsoft.ASP.NET Web API 2.1 OData”的引用——打开NuGet如下图所示:

image_thumb4

第三步:配置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这两个字段,但个信息是没必要给客户端的。,

image

十分幸运的是我们只需要去配置一下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();}
复制代码

源码地址:https://github.com/fzrain/WebApi.eLearning

作者:FZRAIN
出处:http://fzrain.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

转载于:https://www.cnblogs.com/freeliver54/p/6924535.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Spring 3 MVC处理表单

本文是有关Spring 3的一系列文章的一部分。该系列的上一篇文章可以在此处获得 。 在本文中&#xff0c;我们向Spring MVC迈出了又一步。 [此外&#xff1a; 术语MVC的创建者提供的pdf 。]从上一篇文章构建&#xff0c;让我们添加将“联系人”添加到应用程序所需的代码。 首先&a…

插入排序法之——直接插入排序、折半插入排序、希尔排序

// test20.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<vector> #include<string> #include<queue> #include<stack> #include<cstring> #include<string.h> #include<de…

linux idea 快捷键,Linux 下 IDEA 的 Ctrl+Alt+S

前言这是个困扰我一年多的问题&#xff0c;今天终于解决了……起因一年前将主系统换成 Arch Linux 后&#xff0c;其他一切正常就是 IDEA 的打开设置的快捷键 ctrlalts 失效&#xff0c;让我很是头疼。虽然不是很重要&#xff0c;但是对于我这种强迫症来说别提多难受了……我曾…

修改input的placeholder颜色

1、CSS选择器 因为每个浏览器的CSS选择器有所差异&#xff0c;所以需要针对每个浏览器做单独的设定。 ::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #999; } ::-moz-placeholder { /* Mozil…

解决Spring自动装配中的循环依赖

我认为这篇文章是在企业应用程序开发中使用Spring的最佳实践。 使用Spring编写企业Web应用程序时&#xff0c;服务层中的服务量可能会增加。 服务层中的每个服务可能会消耗其他服务&#xff0c;这些服务将通过Autowire注入。 问题&#xff1a;当服务数量开始增加时&#xff0…

01.MD5加密

namespace _01.MD5加密{ class Program { static void Main(string[] args) { //MD5加密就是给想要的密码或者其它字符加密 //如果字符串被加密成MD5值之后,是不可逆的. //字符串123 的MD5 64位加密形式是 202cb962ac59075b964b07152d234b70 Console.WriteLine("请输入需要…

C语言数字3转变字符 3 程序,大学c语言知识点总结

大学c语言知识点总结C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。一起来看看大学c语言知识点总结吧!大学c语言知识点总结1、编译预处理不是C语言的一部分&#xff0c;不再运行时间。C语言编…

接触Jenkins(Hudson)API,第1部分

哪一个-哈德森还是詹金斯&#xff1f; 都。 几个月前&#xff0c;我开始使用Hudson v1.395来从事这个小项目&#xff0c;在出现巨大分歧之后又回到了这个项目。 我以此为契机&#xff0c;看我将来选择永久搬到詹金斯时是否会遇到任何重大问题。 有很多麻烦-最值得注意的是&…

使用javascript模拟常见数据结构(四)

七、树 树是一种非线性的分层的数据结构&#xff0c;在现实生活中比较常见的例子比如家谱和公司的组织架构图&#xff0c;如下所示&#xff1a; 一个树结构存在着一系列的父子结构&#xff0c;并且有着一个根节点&#xff0c;这种结构本质上表明了一对多的关系。 那&#xff0c…

C语言中实际参数太多,c – 宏的实际参数太多了?

码&#xff1a;#include using namespace std;#define ADD(x,y) ((x)(y))int main( int argc, char** argv ){cout << ADD(1,2,) << endl;return 0;}编译器输出&#xff1a;1>Compiling…1>main.cpp1>c:\warn_test\main.cpp(9) : warning C4002: too many…

Web开发框架–第2部分:Play Framework 2.0

作为 评估系列 的第一个候选人&#xff0c; 我们回顾了 Play Framework v2.0 。 可以从Play 文档站点获得本文所使用的教程和参考文档。 本文的第一部分将介绍我们建议对每个框架执行的一组任务&#xff0c;然后继续评估每个标准项。 在开发工作站中安装框架 非常简单&#…

最全Pycharm教程(10)——Pycharm调试器总篇

最全Pycharm教程&#xff08;1&#xff09;——定制外观 最全Pycharm教程&#xff08;2&#xff09;——代码风格 最全Pycharm教程&#xff08;3&#xff09;——代码的调试、执行 最全Pycharm教程&#xff08;4&#xff09;——有关Python解释器的相关配置 最全Pycharm教程&am…

Looper.prepare()和Looper.loop()

什么时候需要 Looper Looper用于封装了android线程中的消息循环&#xff0c;默认情况下一个线程是不存在消息循环&#xff08;message loop&#xff09;的&#xff0c;需要调用Looper.prepare()来给线程创建一个消息循环&#xff0c;调用Looper.loop()来使消息循环起作用&#…

超速问题的c语言编程,超速行驶问题--精选.doc

超速行驶问题摘要本文主要研究的是探讨驱车从始发地至目的地的最短时间路径问题和最少花费问题&#xff0c;以及在超速情况下的最短时间和最少花费问题。首先&#xff0c;从整个题目的两个问题入手&#xff0c;发现两个问题都是优化问题&#xff0c;具有一定的联系。然后针对第…

重新查看Play Framework发布的值

与Play Framework 2.0一起使用发布的值而不定义表单映射&#xff0c;可能不像Play 1.x那样明显&#xff0c;这就是为什么我要编写此快速备忘单。 对于此快速示例&#xff0c;让我们定义以下视图&#xff1a; app / views / index.scala.html (message: String)message: messa…

matlab 微积分

符号变量&#xff0c;symbolic variable 1. 高阶导数 高阶导数的计算&#xff0c;当然可以用手工的方式&#xff0c;但显然这种机械重复的推导&#xff0c;更适用于计算机的计算方式&#xff1a; f(x)sinxx24x3⇒d4fdx4>> syms x; >> f sin(x) / (x^24*x3); >&…

如何查看Ubuntu版本,以及Linux内核版本??

查看Ubuntu版本&#xff1a; 方法一&#xff1a; cat /etc/issue 方法二&#xff1a; sudo lsb_release -a 查看内核版本&#xff1a; uname -r 转载于:https://www.cnblogs.com/tanrong/p/6937749.html

c语言编码风格,讲嵌入式C语言编码风格.ppt

讲嵌入式C语言编码风格目 录 简介及说明 语言规则 1.基础 2.数据 3.说明与表达式 4.函数 5.内存及资源 6.源文件 风格指导 7.程序书写 8.命名 9.文档 简介及说明 正确性 易维护性 易移植性 代码的高效性 语言规则——基础 编写清晰表达设计思路和意图的代码 针对易读来优化代码…

使用Gradle引导旧式Ant构建

Gradle提供了几种不同的方式来利用您现有的对Ant的投资&#xff0c;包括积累的知识和您已经放入构建文件中的时间。 这可以极大地方便将Ant生成的项目移植到Gradle的过程&#xff0c;并为您提供逐步进行此操作的路径。 Gradle文档在描述如何在Gradle构建脚本中使用Ant方面做得很…

实现chrome扩展启动本地进程 - 补充

实现chrome扩展启动本地进程 - 补充 标签&#xff1a; chrome扩展启动本地程序访问本地磁盘2014-10-17 11:42 6753人阅读 评论(17) 收藏 举报分类&#xff1a;Chrome Plugin版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 示例 主要包含如下部分 c…