Click to Rate and Give Feedback
This page is specific to
Microsoft Visual Studio 2008/.NET Framework 3.5

Other versions are also available for the following:
Service Operations and Interceptors (ADO.NET Data Services Framework)

ADO.NET Data Services enable definition of service operations and/or interceptors to extend the model of mapping URIs to resources.

Adding Business Logic to a Data Service

Service operations can be used when business logic is required, for example to implement validation logic or security. Service operations allow the developer to define a method on the server, which, like other ADO.NET Data Service resources, is identified by a URI. These service operations are methods added to the class derived from DataService that represents the data service.

Creating Service Operations

To implement a service operation, define a public instance-method as part of the data service class derived from the DataService class representing the data service.

  • The method must accept only [in] parameters.

    • If parameters are defined, the type of each parameter must be a primitive type.

  • The method must return void, IEnumerable<T>, IQueryable<T>, T, or a primitive class such as integer or string.

    • T MUST be a class that represents an entity type in the data model being exposed by the data service.

    • In order to support query options such as sorting, paging, and filtering, service operation methods should return IQueryable<T>.

  • The method must be annotated with the [WebGet] or [WebInvoke] attribute.

    • [WebGet] enables the method to be invoked using a GET request.

    • [WebInvoke] enables the method to be invoked using a PUT, POST, or DELETE request.

  • A service operation may be annotated with the SingleResultAttribute that specifies that the return value from the method is a single entity rather than a collection of entities. This distinction dictates the resulting serialization of the response. For example, when using AtomPub serialization, a single resource type instance is represented as an entry element and a set of instances as a feed element.

If a method does not follow the conventions defined above, it will not be exposed as a service operation within the data service.

Addressing Service Operations

According to the ADO.NET Data Service Protocol specification, service operations are addressed by placing the name of the method in the first path segment of a URI. Additional path segments or query options may be added to the URI depending on the return type of the service operation.

Valid Return Types URI Rules

Void

A single path segment that is the name of the service operation is allowed.

System query options are not allowed.

IEnumerable<T>

A single path segment that is the name of the service operation is allowed.

System query options are not allowed.

IQueryable<T>

Additional URI path segments according to the path construction rules in the ADO.NET Data Service Specifications specification are allowed.

System query options are allowed.

Adding Service Operations

The following example implements a service operation on a data service exposing an Entity Framework-based model.

public class Northwind : 
           DataService<NorthwindModel.NorthwindEntities>
{
public static void InitializeService(IDataServiceConfiguration config)
    {
       // Entity sets access configuration.
        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);

        // Service operations access configuration.
        config.SetServiceOperationAccessRule("OrdersByCity",
                  ServiceOperationRights.All);
        }

    [WebGet]
    public IQueryable<Orders> OrdersByCity(string city)
    {
        if (string.IsNullOrEmpty(city))
        {
            throw new ArgumentNullException("city",
                      "You must provide a city name argument");
        }

        return this.CurrentDataSource.Orders.Where(
            "it.ShipCity = @city", 
            new ObjectParameter("city", city));
    }
}

To invoke the service operation, the following URI is used:

http://server/Northwind.svc/OrdersByCity?city='London'

Because the return type of the service operation is IQueryable<T>, additional URI segments are permitted. For example, the following URIs are valid:

http://server/Northwind.svc/OrdersByCity?city='London'&$top=2
http://server/Northwind.svc/OrdersByCity?city='London'&$top=10&$orderby=OrderID

Service Operations Access Control

Service-wide visibility of service operations is controlled by a method on the IDataServiceConfiguration class in much the same way that entity set visibility is controlled. For example, to make the CustomersByCity method in the example above accessible, the code in the following figure is added to the class derived from DataService.

public class Northwind : DataService<NorthwindEntities>
    {
        public static void InitializeService(
                                   IDataServiceConfiguration config)
        {
            config.SetServiceOperationAccessRule("CustomersByCity", 
                                          ServiceOperationRights.All);
        }

        [WebGet]
        public IQueryable<Customer> CustomersByCity(string city)
        {… }
     }

Interceptors

ADO.NET Data Services enable a data service developer to intercept the request/response pipeline and inject custom validation logic. In ADO.NET Data Services, interceptors play a dual role; they enable validation logic to be added to the processing pipeline and provide a place to insert custom authorization policy on a per request basis.

NoteNote

Query interceptors cannot take parameters.

Request/URI Processing

When a GET request is received by a data service, the request URI is processed and any query interception methods defined on the data service are called. The following example shows implementation of query interceptor method that intercepts the GET request to orders. This interceptor returns only orders assigned to the customer where CustomerID=="AROUT". More code would be needed authenticate the user sending the request so that this method would return orders assigned to each user.

    [QueryInterceptor("Orders")]
    public Expression<Func<Orders, bool>> FilterOrdersByCustomer()
    {
        return o => o.Customers.CustomerID == "AROUT";
    }

See Also

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Site Feedback
Page view tracker