Bin deploying WCF Data Services

Programming, error messages and sample code > ASP.NET
If you’re bin-deploying WCF Data Services you need to make sure that the .svc file contains the right version string (or no version string).

What’s Bin Deploy?

In a nutshell, bin deploy is the term for copying and pasting a folder to a remote machine and expecting it to work without any other prerequisites. In our case, we clearly still have the IIS prerequisite, but you shouldn’t have to run an installer on the server that GACs the Microsoft.Data.Services DLL.

Bin deploy is frequently necessary when dealing with hosted servers, where you may not have rights to install assemblies to the GAC. Bin deploy is also extremely useful in a number of other environments as it decreases the barriers to hosting a WCF Data Service. (Imagine not having to get your ops team to install something in order to try out WCF Data Services!)

Replicating the Problem

First, let’s walk through what’s actually happening. I’m going to do this in Visual Studio 2012, but this would happen similarly in Visual Studio 2010.

First, create an Empty ASP.NET Web Application. Then right-click the project and choose Add > New Item. Select WCF Data Service, assign the service a name, and click Add. (Remember that in Visual Studio 2012, the item template actually adds the reference to the NuGet package on your behalf. If you’re in Visual Studio 2010, you should add the NuGet package now.)

Stub enough code into the service to make it load properly. In our case, this is actually enough to load the service (though admittedly it’s not very useful):

using System.Data.Services;

namespace OData101.UpdateTheSvcFileWhenBinDeploying
{
    public class BinDeploy : DataService<DummyContext> { }

    public class DummyContext { }
}

Press F5 to debug the project. While the debugger is attached, open the Modules window (Ctrl+D,M). Notice that Microsoft.Data.Services 5.0.0.50627 is loaded:

Now update your NuGet package to 5.0.1 or some subsequent version. (In this example I updated to 5.0.2.) Debug again, and look at the difference in the Modules window:

In this case we have two versions of Microsoft.Data.Services loaded. We pulled 5.0.2 from the bin deploy folder and we still have 5.0.0.50627 loaded from the GAC. Were you to bin deploy this application as-is, it would fail on the server with an error similar to the following:

Could not load file or assembly 'Microsoft.Data.Services, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

So why is the service loading both assemblies? If you look at your .svc file (you need to right-click it and choose View Markup), you’ll see something like the following line in it:

<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Service="OData101.UpdateTheSvcFileWhenBinDeploying.BinDeploy" %>

That 5.0.0.0 string is what is causing the GACed version of Microsoft.Data.Services to be loaded.

Solution:
Change the version number to the right number. The first three digits (major/minor/patch) are the significant digits; assembly resolution will ignore the final digit.
<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Service="OData101.UpdateTheSvcFileWhenBinDeploying.BinDeploy" %>