本文转自:https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/calling-an-odata-service-from-a-net-client

by Mike Wasson+

Download Completed Project+

This tutorial shows how to call an OData service from a C# client application.+

Software versions used in the tutorial

+

In this tutorial, I'll walk through creating a client application that calls an OData service. The OData service exposes the following entities:+

    • Product
    • Supplier
    • ProductRating

+

+

The following articles describe how to implement the OData service in Web API. (You don't need to read them to understand this tutorial, however.)+

+

Generate the Service Proxy

The first step is to generate a service proxy. The service proxy is a .NET class that defines methods for accessing the OData service. The proxy translates method calls into HTTP requests.+

+

Start by opening the OData service project in Visual Studio. Press CTRL+F5 to run the service locally in IIS Express. Note the local address, including the port number that Visual Studio assigns. You will need this address when you create the proxy.+

Next, open another instance of Visual Studio and create a console application project. The console application will be our OData client application. (You can also add the project to the same solution as the service.)+

Note

The remaining steps refer the console project.+

In Solution Explorer, right-click References and select Add Service Reference.+

+

In the Add Service Reference dialog, type the address of the OData service:+

consoleCopy
http://localhost:port/odata

where port is the port number.+

+

For Namespace, type "ProductService". This option defines the namespace of the proxy class.+

Click Go. Visual Studio reads the OData metadata document to discover the entities in the service.+

+

Click OK to add the proxy class to your project.+

+

Create an Instance of the Service Proxy Class

Inside your Main method, create a new instance of the proxy class, as follows:+

C#Copy
using System;
using System.Data.Services.Client;
using System.Linq; namespace Client
{
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1234/odata/");
var container = new ProductService.Container(uri); // ...
}
}
}

Again, use the actual port number where your service is running. When you deploy your service, you will use the URI of the live service. You don't need to update the proxy.+

The following code adds an event handler that prints the request URIs to the console window. This step isn't required, but it's interesting to see the URIs for each query.+

C#Copy
container.SendingRequest2 += (s, e) =>
{
Console.WriteLine("{0} {1}", e.RequestMessage.Method, e.RequestMessage.Url);
};

Query the Service

The following code gets the list of products from the OData service.+

C#Copy
class Program
{
static void DisplayProduct(ProductService.Product product)
{
Console.WriteLine("{0} {1} {2}", product.Name, product.Price, product.Category);
} // Get an entire entity set.
static void ListAllProducts(ProductService.Container container)
{
foreach (var p in container.Products)
{
DisplayProduct(p);
}
} static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:18285/odata/");
var container = new ProductService.Container(uri);
container.SendingRequest2 += (s, e) =>
{
Console.WriteLine("{0} {1}", e.RequestMessage.Method, e.RequestMessage.Url);
}; // Get the list of products
ListAllProducts(container);
}
}

Notice that you don't need to write any code to send the HTTP request or parse the response. The proxy class does this automatically when you enumerate the Container.Products collection in the foreach loop.+

When you run the application, the output should look like the following:+

consoleCopy
GET http://localhost:60868/odata/Products
Hat 15.00 Apparel
Scarf 12.00 Apparel
Socks 5.00 Apparel
Yo-yo 4.95 Toys
Puzzle 8.00 Toys

To get an entity by ID, use a where clause.+

C#Copy
// Get a single entity.
static void ListProductById(ProductService.Container container, int id)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
DisplayProduct(product);
}
}

For the rest of this topic, I won't show the entire Main function, just the code needed to call the service.+

Apply Query Options

OData defines query options that can be used to filter, sort, page data, and so forth. In the service proxy, you can apply these options by using various LINQ expressions.+

In this section, I'll show brief examples. For more details, see the topic LINQ Considerations (WCF Data Services) on MSDN.+

Filtering ($filter)

To filter, use a where clause. The following example filters by product category.+

C#Copy
// Use the $filter option.
static void ListProductsInCategory(ProductService.Container container, string category)
{
var products =
from p in container.Products
where p.Category == category
select p;
foreach (var p in products)
{
DisplayProduct(p);
}
}

This code corresponds to the following OData query.+

consoleCopy
GET http://localhost/odata/Products()?$filter=Category eq 'apparel'

Notice that the proxy converts the where clause into an OData $filter expression.+

Sorting ($orderby)

To sort, use an orderby clause. The following example sorts by price, from highest to lowest.+

C#Copy
// Use the $orderby option
static void ListProductsSorted(ProductService.Container container)
{
// Sort by price, highest to lowest.
var products =
from p in container.Products
orderby p.Price descending
select p; foreach (var p in products)
{
DisplayProduct(p);
}
}

Here is the corresponding OData request.+

consoleCopy
GET http://localhost/odata/Products()?$orderby=Price desc

Client-Side Paging ($skip and $top)

For large entity sets, the client might want to limit the number of results. For example, a client might show 10 entries at a time. This is called client-side paging. (There is also server-side paging, where the server limits the number of results.) To perform client-side paging, use the LINQ Skip and Take methods. The following example skips the first 40 results and takes the next 10.+

C#Copy
// Use $skip and $top options.
static void ListProductsPaged(ProductService.Container container)
{
var products =
(from p in container.Products
orderby p.Price descending
select p).Skip(40).Take(10); foreach (var p in products)
{
DisplayProduct(p);
}
}

Here is the corresponding OData request:+

consoleCopy
GET http://localhost/odata/Products()?$orderby=Price desc&$skip=40&$top=10

Select ($select) and Expand ($expand)

To include related entities, use the DataServiceQuery<t>.Expand method. For example, to include the Supplier for each Product:+

C#Copy
// Use the $expand option.
static void ListProductsAndSupplier(ProductService.Container container)
{
var products = container.Products.Expand(p => p.Supplier);
foreach (var p in products)
{
Console.WriteLine("{0}\t{1}\t{2}", p.Name, p.Price, p.Supplier.Name);
}
}

Here is the corresponding OData request:+

consoleCopy
GET http://localhost/odata/Products()?$expand=Supplier

To change the shape of the response, use the LINQ select clause. The following example gets just the name of each product, with no other properties.+

C#Copy
// Use the $select option.
static void ListProductNames(ProductService.Container container)
{ var products = from p in container.Products select new { Name = p.Name };
foreach (var p in products)
{
Console.WriteLine(p.Name);
}
}

Here is the corresponding OData request:+

consoleCopy
GET http://localhost/odata/Products()?$select=Name

A select clause can include related entities. In that case, do not call Expand; the proxy automatically includes the expansion in this case. The following example gets the name and supplier of each product.+

C#Copy
// Use $expand and $select options
static void ListProductNameSupplier(ProductService.Container container)
{
var products =
from p in container.Products
select new
{
Name = p.Name,
Supplier = p.Supplier.Name
};
foreach (var p in products)
{
Console.WriteLine("{0}\t{1}", p.Name, p.Supplier);
}
}

Here is the corresponding OData request. Notice that it includes the $expand option.+

consoleCopy
GET http://localhost/odata/Products()?$expand=Supplier&$select=Name,Supplier/Name

For more information about $select and $expand, see Using $select, $expand, and $value in Web API 2.+

Add a New Entity

To add a new entity to an entity set, call AddToEntitySet, where EntitySet is the name of the entity set. For example, AddToProducts adds a new Product to the Products entity set. When you generate the proxy, WCF Data Services automatically creates these strongly-typed AddTo methods.+

C#Copy
// Add an entity.
static void AddProduct(ProductService.Container container, ProductService.Product product)
{
container.AddToProducts(product);
var serviceResponse = container.SaveChanges();
foreach (var operationResponse in serviceResponse)
{
Console.WriteLine(operationResponse.StatusCode);
}
}

To add a link between two entities, use the AddLink and SetLink methods. The following code adds a new supplier and a new product, and then creates links between them.+

C#Copy
// Add entities with links.
static void AddProductWithSupplier(ProductService.Container container,
ProductService.Product product, ProductService.Supplier supplier)
{
container.AddToSuppliers(supplier);
container.AddToProducts(product);
container.AddLink(supplier, "Products", product);
container.SetLink(product, "Supplier", supplier);
var serviceResponse = container.SaveChanges();
foreach (var operationResponse in serviceResponse)
{
Console.WriteLine(operationResponse.StatusCode);
}
}

Use AddLink when the navigation property is a collection. In this example, we are adding a product to the Products collection on the supplier.+

Use SetLink when the navigation property is a single entity. In this example, we are setting the Supplier property on the product.+

Update / Patch

To update an entity, call the UpdateObject method.+

C#Copy
static void UpdatePrice(ProductService.Container container, int id, decimal price)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
product.Price = price;
container.UpdateObject(product);
container.SaveChanges(SaveChangesOptions.PatchOnUpdate);
}
}

The update is performed when you call SaveChanges. By default, WCF sends an HTTP MERGE request. The PatchOnUpdate option tells WCF to send an HTTP PATCH instead.+

Note

Why PATCH versus MERGE? The original HTTP 1.1 specification (RCF 2616) did not define any HTTP method with "partial update" semantics. To support partial updates, the OData specification defined the MERGE method. In 2010, RFC 5789 defined the PATCH method for partial updates. You can read some of the history in this blog post on the WCF Data Services Blog. Today, PATCH is preferred over MERGE. The OData controller created by the Web API scaffolding supports both methods.+

If you want to replace the entire entity (PUT semantics), specify the ReplaceOnUpdate option. This causes WCF to send an HTTP PUT request.+

C#Copy
container.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);

Delete an Entity

To delete an entity, call DeleteObject.+

C#Copy
static void DeleteProduct(ProductService.Container container, int id)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
container.DeleteObject(product);
container.SaveChanges();
}
}

Invoke an OData Action

In OData, actions are a way to add server-side behaviors that are not easily defined as CRUD operations on entities.+

Although the OData metadata document describes the actions, the proxy class does not create any strongly-typed methods for them. You can still invoke an OData action by using the generic Execute method. However, you will need to know the data types of the parameters and the return value.+

For example, the RateProduct action takes parameter named "Rating" of type Int32 and returns a double. The following code shows how to invoke this action.+

C#Copy
int rating = 2;
Uri actionUri = new Uri(uri, "Products(5)/RateProduct");
var averageRating = container.Execute<double>(
actionUri, "POST", true, new BodyOperationParameter("Rating", rating)).First();

For more information, seeCalling Service Operations and Actions.+

One option is to extend the Container class to provide a strongly typed method that invokes the action:+

C#Copy
namespace ProductServiceClient.ProductService
{
public partial class Container
{
public double RateProduct(int productID, int rating)
{
Uri actionUri = new Uri(this.BaseUri,
String.Format("Products({0})/RateProduct", productID)
); return this.Execute<double>(actionUri,
"POST", true, new BodyOperationParameter("Rating", rating)).First();
}
}
}

[转]Calling an OData Service From a .NET Client (C#)的更多相关文章

  1. [转]Consuming a OData Service in a Client Application (WCF Data Services)

    本文转自:https://msdn.microsoft.com/zh-tw/library/dd728282(v=vs.103).aspx WCF Data Services 5.0   其他版本   ...

  2. [转]Work With Odata in Web API: Create Your First Odata Service

    本文转自:http://www.c-sharpcorner.com/UploadFile/dacca2/work-with-odata-in-web-api-create-your-first-oda ...

  3. 使用SAP云平台的destination消费Internet上的OData service

    通过SAP云平台上的destination我们可以消费Internet上的OData service或者其他通过HTTP方式暴露出来的服务. 创建一个新的destination: 维护如下属性: 点击 ...

  4. 创建OData Service(基于ASP.NET 4.6.1, EF 6),Part I:Project initialize

    由于ASP.NET Core 1处于RC阶段,加上OData WebAPI 对ASP.NET Core 1的跟进不是很积极,基于ASP.NET Core 1的Alpha 1版本已经N月没有check ...

  5. 如何用SAP WebIDE的Fiori创建向导基于ABAP OData service快速创建UI5应用

    如果我们手上已经有可以正常工作的OData服务,无论位于ABAP on-premise系统还是public上的internet OData service,都可以用SAP WebIDE里的Fiori创 ...

  6. UI5-文档-4.26-(Optional) Remote OData Service

    到目前为止,我们已经使用了本地JSON数据,但是现在我们将访问一个真正的OData服务来可视化远程数据. 用可公开获得的Northwind OData服务显示并替换发票模型的JSONModel类型,以 ...

  7. 找出OData service出错根源的小技巧

    SAP的Fiori应用是通过OData和后台交互的.在使用Fiori应用时您可能会遇到这样的错误消息: 这个错误消息没有包含有助于partner或者客户定位问题根源的线索. 下面是如何在后台找出问题根 ...

  8. 使用Excel消费C4C的OData service

    步骤比较简单, 打开Excel的标签Data->From Other Sources->From OData Data Feed: 输入如下url: https://.c4c.saphyb ...

  9. Calling the Web Service dynamically (.NET 动态访问Web Service)

    针对.NET平台下的WebService访问,为达到不添加引用的情况下,动态调用外部服务. 主体方法: public class WebServiceHelper { //Calling the We ...

随机推荐

  1. SQL Server数据库的基础脚本编程

    数据库脚本的基础编程 Go批量处理语句 用于同时处理多条语句 use指定数据库或表 use master --创建数据库 go use Student --创建表(Student)表示数据库 go 创 ...

  2. 再编写代码中报错:CS8107 C# 7.0 中不支持功能“xxxxxx”。请使用 7.1 或更高的语言版本。

    解决方法:项目右键属性 ---> 生成 ---> 找到最下面的高级按钮,点击高级按钮 ---> 常规 ---> 语言版本 ---> 选择 C#最新次要版本,或者比当前版本 ...

  3. Android移动客户端性能测试浅谈——电量

    本文由作者张迎贞授权网易云社区发布. APP性能测试除了需要监控PCU.内存占用.流量等,还需要获取APP的电量数据,测试在可接受范围内,避免APP出现过度消耗电量的现象.手机有很多硬件模块:CPU, ...

  4. python网络编程--协程

      1.协程 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的.. 需要强调的是: 1. pyt ...

  5. ClamAV学习【6】—— cli_load函数浏览

    (老爸回家,就放开心和他到处走,累……趁其和老妈聊天之际,再继续看代码) 参数选项,加载病毒都浏览得七七八八了,这里就贴个简单的函数注释吧.哈哈. 代码注释如下: int cli_load(const ...

  6. RPC 简单小试

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器 ...

  7. junit启动tomcat来进行单元测试

    1.pom.xml配置下载需要的jar.   <dependency>            <groupId>junit</groupId>            ...

  8. SpringMvc渲染视图

    这篇博文讨论的问题是从ModelAndView如何渲染到页面. 首先要知道每个请求处理完之后都会返回一个ModelAndView对象. 这里我分6种情况来分析,代表6种返回类型: ModelAndVi ...

  9. day 28 :进程相关,进程池,锁,队列,生产者消费者模式

    ---恢复内容开始--- 前情提要: 一:进程Process  1:模块介绍 from multiprocessing import Process from multiprocessing impo ...

  10. leetcode-219-Contains Duplicate II(使用set来判断长度为k+1的闭区间中有没有重复元素)

    题目描述: Given an array of integers and an integer k, find out whether there are two distinct indices i ...