Home > .NET, Programming > WCF Data Services Tip

WCF Data Services Tip

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="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">
  <workspace>
    <atom:title>Default</atom:title>
    <collection href="ZIPUSAs">
      <atom:title>ZIPUSAs</atom:title>
    </collection>
  </workspace>
</service>

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.

Advertisements
Categories: .NET, Programming
  1. No comments yet.
  1. July 14, 2010 at 10:12 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: