[转]Calling an OData Service From a .NET Client (C#)

本文转自: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();
        }
    }
}
时间: 2024-10-10 09:57:33

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

十分钟玩转Fiori App中的ODATA Service

我们谈了了很多关于OData的话题,但是Fiori APP到底是怎么通过SAP Gateway调用OData Service的呢? 今天我们通过一个Fiori App实例来分析一下. 首先我们启动Fiori App "Manage Journal Entries",这个APP我已经引用了好几次,就不再介绍了. 输入简单的过滤参数,公司代码和财年信息. 点击执行,应用返回相应的财务凭证的Header信息列表. SAP Fiori应用是怎么通过前端的SAP UI5来调用后端系统得到凭证的H

从OData Service到SAPUI5一站式开发指南(SAP FIORI全栈开发)

前言 今年可以说是SAP FIORI达到了井喷式的发展,越来越多的人开始关注的SAP FIORI的动向,作为SAP开发的自身爱好者,前言技术的分享这,我从2013年开始涉足SAP FIORI 领域,并开发了众多的FIORI应用,今天给大家分享一下,传统的SAP FIORI开发我们通常要做哪些步骤. 后台数据库 对于传统的ECC系统, 之前做过很多都是Any DB, 其实前端(SAPUI5应用)不管如何更改,如何维护,最终的归宿都在SE11创建的数据库表中,所以我们需要对数据库表的创建和维护有一个

通过SAP云平台上的destination我们可以消费Internet上的OData service

通过SAP云平台上的destination我们可以消费Internet上的OData service或者其他通过HTTP方式暴露出来的服务. 创建一个新的destination: 维护如下属性: 点击Check Connection确保该destination正常工作: 在WebIDE里新建一个Fiori Worklist Application: 从Service url选择之前创建好的destination: 在Object Collection里选择Alphabetical_list_of

SAP OData service的执行是如何从Gateway系统转交到backend系统

下面是我今天研究的后台OData数据的model以及如何在IE里面consume: SPRO里面: 这个model provider class定义了LWM_CUSTOMER_BRIEFING这个model的所有structure,以及structure之间的相互关系. 现在没有一个图形化界面的tool来做modelling,我们只能在CL_LWM_CB_ADAPTER_MDP的DEFINE里面定义model的structure.具体做法是预先定义好后台要使用的entity的data type,

Deploying OpenFire for IM (instant message) service (TCP/IP service) with database MySQL , client Spark on linux部署OpenFire IM 消息中间件服务

Are you a hacker? How to build another QQ/Wechat/whatsapp/skype/imessage? Let's go through this!!!! Materials: A linux/unix/windows/mac computer/server, and do some basic things! Are you feeling high? Okay, let's ride the rocket! Get materials: 1. A

[WCF] - Odata Service 访问失败,查看具体错误信息的方法

Issue 解决 为 Data Service 配置属性如下:[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)] 参考 http://salvoz.com/blog/2011/02/18/where-are-the-server-logs/

使用Excel消费C4C的OData service

步骤比较简单, 打开Excel的标签Data->From Other Sources->From OData Data Feed: 输入如下url: https://<your tenant>.c4c.saphybriscloud.cn/sap/byd/odata/v1/c4codata/ 选择AccountCollection: 这个例子我把C4C系统里所有的account都下载并显示在Excel里: 要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"

Calling a Web API From a .NET Client (C#)

by Mike Wasson+ Download Completed Project This tutorial shows how to call a web API from a .NET application, using System.Net.Http.HttpClient.+ In this tutorial, we will write an client application that consumes the following web API.+ Action HTTP m

[转]ASP.NET web API 2 OData enhancements

本文转自:https://www.pluralsight.com/blog/tutorials/asp-net-web-api-2-odata-enhancements Along with the release of Visual Studio 2013 came a new release of ASP.NET MVC (called MVC 5) and ASP.NET Web API (called Web API 2). Part of the enhancements to the