Export (0) Print
Expand All
This topic has not yet been rated - Rate this topic

Calling Service Operations and Actions (WCF Data Services)

The Open Data Protocol (OData) defines both service operations and service actions for a data service. Like other data service resources, service operations and service actions are addressed by using URIs. Both service operation and actions can return collections of entity types; single entity type instances; primitive types, such as integer and string; and null (Nothing in Visual Basic). Unlike service operations, service actions can be bound to data model resources and must be called with an HTTP POST request because they have side-effects on the system. For more information, see Service Operations (WCF Data Services) and Using OData Actions to implement server-side behavior.

Both service operations and service actions are exposed in the metadata returned by a data service that implements the OData. In the metadata, both are represented as FunctionImport elements. When generating the strongly-typed DataServiceContext, the Add Service Reference and DataSvcUtil.exe tools ignore this element. Because of this, you will not find a method on the context that can be used to call a service operation directly. However, you can still use the WCF Data Services client to call service operations in one of these two ways:

The following considerations apply when using the WCF Data Services client to call service operations.

This section contains the following examples of how to call service operations by using the WCF Data Services client library:

Calling Execute<T> to Return a Collection of Entities

The following example calls a service operation named GetOrdersByCity, which takes a string parameter of city and returns an IQueryable<T>:

// Define the service operation query parameter.
string city = "London";

// Define the query URI to access the service operation with specific 
// query options relative to the service URI.
string queryString = string.Format("GetOrdersByCity?city='{0}'", city)
    + "&$orderby=ShippedDate desc"
    + "&$expand=Order_Details";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute the service operation that returns all orders for the specified city.
    var results = context.Execute<Order>(new Uri(queryString, UriKind.Relative));

    // Write out order information.
    foreach (Order o in results)
    {
        Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

        foreach (Order_Detail item in o.Order_Details)
        {
            Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                item.ProductID, item.Quantity));
        }
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

In this example, the service operation returns a collection of Order objects with related Order_Detail objects.

Using CreateQuery<T> to Return a Collection of Entities

The following example uses the CreateQuery<T>(String) to return a DataServiceQuery<TElement> that is used to call the same GetOrdersByCity service operation:

// Define the service operation query parameter.
string city = "London";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Use the CreateQuery method to create a query that accessess
// the service operation passing a single parameter.       
var query = context.CreateQuery<Order>("GetOrdersByCity")
    .AddQueryOption("city", string.Format("'{0}'", city))
    .Expand("Order_Details");

try
{
    // The query is executed during enumeration.
    foreach (Order o in query)
    {
        Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

        foreach (Order_Detail item in o.Order_Details)
        {
            Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                item.ProductID, item.Quantity));
        }
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

In this example, the AddQueryOption(String, Object) method is used to add the parameter to the query, and the Expand(String) method is used to include related Order_Details objects in the results.

Calling Execute<T> to Return a Single Entity

The following example calls a service operation named GetNewestOrder that returns only a single Order entity:

// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "GetNewestOrder";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns only the newest single order.
    Order order
        = (context.Execute<Order>(new Uri(queryString, UriKind.Relative)))
        .FirstOrDefault();

    // Write out order information.
    Console.WriteLine(string.Format("Order ID: {0}", order.OrderID));
    Console.WriteLine(string.Format("Order date: {0}", order.OrderDate));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

In this example, the FirstOrDefault<TSource>(IEnumerable<TSource>) method is used to request only a single Order entity on execution.

Calling Execute<T> to Return a Collection of Primitive Values

The following example calls a service operation that returns a collection of string values:

// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "GetCustomerNames";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns a collection of customer names
    IEnumerable<string> customerNames
        = context.Execute<string>(new Uri(queryString, UriKind.Relative));

    foreach (string name in customerNames)
    {
        // Write out customer information.
        Console.WriteLine(name);
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

Calling Execute<T> to Return a Single Primitive Value

The following example calls a service operation that returns a single string value:

// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "CountOpenOrders";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns the integer 
    // count of open orders.
    int numOrders
        = (context.Execute<int>(new Uri(queryString, UriKind.Relative)))
        .FirstOrDefault();

    // Write out the number of open orders.
    Console.WriteLine(string.Format("Open orders as of {0}: {1}",
        DateTime.Today.Date, numOrders));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

Again in this example, the FirstOrDefault<TSource>(IEnumerable<TSource>) method is used to request only a single integer value on execution.

Calling a Service Operation that Returns No Data

The following example calls a service operation that returns no data:

// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "ReturnsNoData";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns void.
    context.Execute<string>(new Uri(queryString, UriKind.Relative));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

Because not data is returned, the value of the execution is not assigned. The only indication that the request has succeeded is that no DataServiceQueryException is raised.

Calling a Service Operation Asynchronously

The following example calls a service operation asynchronously by calling BeginExecute<TElement>(Uri, AsyncCallback, Object) and EndExecute<TElement>(IAsyncResult):

// Define the service operation query parameter.
string city = "London";

// Define the query URI to access the service operation with specific 
// query options relative to the service URI.
string queryString = string.Format("GetOrdersByCity?city='{0}'", city)
    + "&$orderby=ShippedDate desc"
    + "&$expand=Order_Details";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Execute the service operation that returns 
// all orders for the specified city.
var results = context.BeginExecute<Order>(
    new Uri(queryString, UriKind.Relative),
    OnAsyncExecutionComplete, context);
private static void OnAsyncExecutionComplete(IAsyncResult result)
{
    // Get the context back from the stored state.
    var context = result.AsyncState as NorthwindEntities;

    try
    {
        // Complete the exection and write out the results.
        foreach (Order o in context.EndExecute<Order>(result))
        {
            Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

            foreach (Order_Detail item in o.Order_Details)
            {
                Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                    item.ProductID, item.Quantity));
            }
        }
    }
    catch (DataServiceQueryException ex)
    {
        QueryOperationResponse response = ex.Response;

        Console.WriteLine(response.Error.Message);
    }
}

Because no data is returned, the value returned by the execution is not assigned. The only indication that the request has succeeded is that no DataServiceQueryException is raised.

The following example calls the same service operation asynchronously by using CreateQuery<T>(String):

// Define the service operation query parameter.
string city = "London";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Use the CreateQuery method to create a query that accessess
// the service operation passing a single parameter.       
var query = context.CreateQuery<Order>("GetOrdersByCity")
    .AddQueryOption("city", string.Format("'{0}'", city))
    .Expand("Order_Details");

// Execute the service operation that returns 
// all orders for the specified city.
var results = 
    query.BeginExecute(OnAsyncQueryExecutionComplete, query);
private static void OnAsyncQueryExecutionComplete(IAsyncResult result)
{
    // Get the query back from the stored state.
    var query = result.AsyncState as DataServiceQuery<Order>;

    try
    {
        // Complete the exection and write out the results.
        foreach (Order o in query.EndExecute(result))
        {
            Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

            foreach (Order_Detail item in o.Order_Details)
            {
                Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                    item.ProductID, item.Quantity));
            }
        }
    }
    catch (DataServiceQueryException ex)
    {
        QueryOperationResponse response = ex.Response;

        Console.WriteLine(response.Error.Message);
    }
}
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.