Archive for March, 2010

WCF Data Services Tip

March 31, 2010 1 comment

At work, I’ve been deep diving into OData / ADO.NET Data Services / WCF Data Services or whatever it’s named this week. We had a desire to expose an existing database table internally for Zip Code lookup. Previously, they used operations within an ASMX service, but I wanted to make a more RESTFUL service available.

Within this project, we already were using LINQ-to-SQL for our data access and I decided to use the DataContext exposed by that instead of wiring up an EDM just for that table. Data Services is pretty slick and can handle the LINQ data context. I followed the normal steps and quickly had a service up and running with the following code:

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using Location.DataAccess;
using System.Linq.Expressions;
using System.ServiceModel.Activation;

namespace Location.Service
    public class ZipCodeService : DataService<ZipCodesDataContext>
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
            config.SetEntitySetAccessRule("ZIPUSAs", EntitySetRights.AllRead);
            config.DataServiceBehavior.AcceptCountRequests = true;
            config.DataServiceBehavior.AcceptProjectionRequests = true;
            config.SetEntitySetPageSize("*", 25);
            config.DataServiceBehavior.MaxProtocolVersion = System.Data.Services.Common.DataServiceProtocolVersion.V2;


This works perfectly. I browse to the service and see the following XML:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<service xml:base="http://localhost:10903/ZipCodeService.svc/" xmlns:atom="" xmlns:app="" xmlns="">
    <collection href="ZIPUSAs">

But that Collection title of “ZIPUSAs” just bugs me. So, I go into my DBML and change it to ZipCodes. Hit F5 to run and I get this error:

The server encountered an error processing the request. The exception message is 'Exception has been thrown by the target of an invocation.'. See server logs for more details. The exception stack trace is:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Data.Services.DataServiceConfiguration.InvokeStaticInitialization(Type type)
   at System.Data.Services.DataService`1.CreateConfiguration(Type dataServiceType, IDataServiceMetadataProvider provider)
   at System.Data.Services.DataService`1.CreateProvider()
   at System.Data.Services.DataService`1.HandleRequest()
   at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
   at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Yikes! What happened?

Well, I updated the entity name, but did not update the corresponding string in the ZipCodeService.InitializeService method. I need to change this:

config.SetEntitySetAccessRule("ZIPUSAs", EntitySetRights.AllRead);

to this:

config.SetEntitySetAccessRule("ZipCodes", EntitySetRights.AllRead);

But this continued to seem inelegant to me. I wish that there was a way to have the string change when I refactored my DBML entity.

With a hat tip to @brakower, here is a suggested solution:

config.SetEntitySetAccessRule(typeof(ZipCodes).Name, EntitySetRights.AllRead);

Works great.

Categories: .NET, Programming