How to: Intercept Data Service Messages (WCF Data Services)

With WCF Data Services, you can intercept request messages so that you can add custom logic to an operation. To intercept a message, you use specially attributed methods in the data service. For more information, see Interceptors (WCF Data Services).

The example in this topic uses the Northwind sample data service. This service is created when you complete the WCF Data Services quickstart.

To define a query interceptor for the Orders entity set

  1. In the Northwind data service project, open the Northwind.svc file.

  2. In the code page for the Northwind class, add the following using statement (Imports in Visual Basic).

    Imports System.Linq.Expressions
    
    using System.Linq.Expressions;
    
  3. In the Northwind class, define a service operation method named OnQueryOrders as follows:

    ' Define a query interceptor for the Orders entity set.
    <QueryInterceptor("Orders")> _
    Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))
    
    // Define a query interceptor for the Orders entity set.
    [QueryInterceptor("Orders")]
    public Expression<Func<Order, bool>> OnQueryOrders()
    

To define a change interceptor for the Products entity set

  1. In the Northwind data service project, open the Northwind.svc file.

  2. In the Northwind class, define a service operation method named OnChangeProducts as follows:

    ' Define a change interceptor for the Products entity set.
    <ChangeInterceptor("Products")> _
    Public Sub OnChangeProducts(ByVal product As Product, _
                                ByVal operations As UpdateOperations)
    
    // Define a change interceptor for the Products entity set.
    [ChangeInterceptor("Products")]
    public void OnChangeProducts(Product product, UpdateOperations operations)
    

Example

This example defines a query interceptor method for the Orders entity set that returns a lambda expression. This expression contains a delegate that filters the requested Orders based on related Customers that have a specific contact name. The name is in turn determined based on the requesting user. This example assumes that the data service is hosted within an ASP.NET Web application that uses WCF, and that authentication is enabled. The HttpContext class is used to retrieve the principle of the current request.

' Define a query interceptor for the Orders entity set.
<QueryInterceptor("Orders")> _
Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))
    ' Filter the returned orders to only orders 
    ' that belong to a customer that is the current user.
    Return Function(o) o.Customer.ContactName = _
        HttpContext.Current.User.Identity.Name
End Function
// Define a query interceptor for the Orders entity set.
[QueryInterceptor("Orders")]
public Expression<Func<Order, bool>> OnQueryOrders()
{
    // Filter the returned orders to only orders 
    // that belong to a customer that is the current user.
    return o => o.Customer.ContactName ==
        HttpContext.Current.User.Identity.Name;
}

This example defines a change interceptor method for the Products entity set. This method validates input to the service for an Add or Change operation and raises an exception if a change is being made to a discontinued product. It also blocks the deletion of products as an unsupported operation.

' Define a change interceptor for the Products entity set.
<ChangeInterceptor("Products")> _
Public Sub OnChangeProducts(ByVal product As Product, _
                            ByVal operations As UpdateOperations)
    If operations = UpdateOperations.Change Then
        Dim entry As System.Data.Objects.ObjectStateEntry

        If Me.CurrentDataSource.ObjectStateManager _
            .TryGetObjectStateEntry(product, entry) Then

            ' Reject changes to a discontinued Product.
            ' Because the update is already made to the entity by the time the 
            ' change interceptor in invoked, check the original value of the Discontinued
            ' property in the state entry and reject the change if 'true'.
            If CType(entry.OriginalValues("Discontinued"), Boolean) Then
                Throw New DataServiceException(400, String.Format(
                            "A discontinued {0} cannot be modified.", product.ToString()))
            Else
                Throw New DataServiceException(String.Format( _
                    "The requested {0} could not be found in the data source.", product.ToString()))
            End If
        ElseIf (operations = UpdateOperations.Delete) Then
            ' Block the delete and instead set the Discontinued flag.
            Throw New DataServiceException(400, _
                "Products cannot be deleted; instead set the Discontinued flag to 'true'")
        End If
    End If
End Sub
// Define a change interceptor for the Products entity set.
[ChangeInterceptor("Products")]
public void OnChangeProducts(Product product, UpdateOperations operations)
{
    if (operations == UpdateOperations.Change)
    {
        System.Data.Objects.ObjectStateEntry entry;

        if (this.CurrentDataSource.ObjectStateManager
            .TryGetObjectStateEntry(product, out entry))
        {
            // Reject changes to a discontinued Product.
            // Because the update is already made to the entity by the time the 
            // change interceptor in invoked, check the original value of the Discontinued
            // property in the state entry and reject the change if 'true'.
            if ((bool)entry.OriginalValues["Discontinued"])
            {
                throw new DataServiceException(400, string.Format(
                            "A discontinued {0} cannot be modified.", product.ToString()));
            }
        }
        else
        {
            throw new DataServiceException(string.Format(
                "The requested {0} could not be found in the data source.", product.ToString()));
        }
    }
    else if (operations == UpdateOperations.Delete)
    {
        // Block the delete and instead set the Discontinued flag.
        throw new DataServiceException(400,
            "Products cannot be deleted; instead set the Discontinued flag to 'true'");
    }
}

See Also

Tasks

How to: Define a Service Operation (WCF Data Services)

Other Resources

Defining WCF Data Services