
Using Interceptors to customize a WCF Data Service
If you've been familiar with standard WCF service programming, you probably have been playing with the Message Inspectors, which are one of the WCF extension components for intercepting the request and response messages of service operation calls.
Well, for WCF Data Service, we also have the similar extension component called Interceptors, which can help intercepting the service requests issued from client callers.
By using WCF Data Service Interceptors, we can customize the code logic of certain operations against a given entity set. In this recipe, we will see how to do some customization on the data processing code logic in WCF Data Service by using custom Interceptors.
Getting ready
In this recipe we will build a WCF Data Service based on the Northwind EF data model. The service will expose two data entity sets, one is from the Categories
table, and the other is from the Products
table. For demonstration, we will add two custom Interceptors against these two entity sets so as to change their query and delete behavior.
The source code for this recipe can be found in the \ch01\QIDataServiceSln\
directory.
How to do it...
- Create a new ASP.NET Empty Web Application.
- Create a WCF Data Service with ADO.NET Entity Framework data model (using the Northwind database).
The service will only expose the
Categories
andProducts
entity sets from the data source (see the following screenshot). - Add custom Interceptors in the WCF Data Service class and bind them with the target entity sets.
There are two Interceptors to define here. The first one is a QueryInterceptor against the
Products
entity set. It will restrict the query result so as to expose Product entities that haveUnitsInStock > 0
. The second one is a ChangeInterceptor against theCategories
entity set. By using it, no delete operation is allowed on theCategories
entity set. The following code snippet shows the WCF Data Service class, which includes both Interceptors:public class NWDataService : DataService< NorthwindEntities > { public static void InitializeService(DataServiceConfiguration config) { config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; config.SetEntitySetAccessRule("*", EntitySetRights.All); } // Query Interceptor for Products entity set [QueryInterceptor("Products")] public Expression<Func<Product, bool>> onQueryProducts() { // Only return products that have units in stock return p => p.UnitsInStock > 0; } // Change Interceptor for Categories entity set [ChangeInterceptor("Categories")] public void onChangeCategories (Category cate, UpdateOperations operations) { if (operations == UpdateOperations.Delete) { throw new DataServiceException(400, "Delete operation is not supported on Categories entity set."); } } }
- Launch the service and try accessing the entity sets, which have Interceptors applied.
By accessing the
Products
entity set, we can find that all the entities returned by it have theUnitsInStock
field greater than zero. Also, if we explicitly use query filter to look forProduct
entities that haveUnitsInStock
equal to zero, we will get empty results (see the following screenshot).
How it works...
In the sample service, we have applied a QueryInterceptor on the Products
entity set. Actually, a QueryInterceptor
is just a function, which returns a Lambda expression with the following signature:
Func<[Entity Type], bool>
Then, why does it use an expression instead of a delegate function directly? The reason is that by using an expression, it is more convenient for the underlying WCF Data Service runtime to forward such QueryInterceptor
injected code logic to the actual query provider (such as the ADO.NET Entity Framework provider, which will generate T-SQL based on the query) that will fetch the data from the backend data source.
QueryInterceptor will be invoked when HTTP GET based query requests are received against the target entity set; while ChangeInterceptor will be invoked when update/modify operations are called. In this sample, our onChangeCategories
Interceptor will check the incoming request to see if it is a delete operation against the Categories
entity set. If the checking result is true
, a DataServiceException
will be thrown out. In a real-world case, we can apply more complicated code logic to change the default update/modify behavior against the target entity sets.
There's more...
For more information about using Interceptors in WCF Data Service, you can read the following MSDN reference:
Interceptors (WCF Data Services) available at http://msdn.microsoft.com/en-us/library/dd744842.aspx
See also
- Building an OData service via WCF Data Service and ADO.NET Entity Framework recipe