How To: Include XmlSerializers in your ClickOnce Application

Have you ever noticed that when your application has a web reference, and you go to publish that web reference, the expected XmlSerializers assembly is not written into the application manifest, nor is it deployed with the application? You haven't? Not too many people have: it rarely comes up in the forums I scan, but we have received a couple of support calls about this. The answers I have given in the past include things like:

  • Expose the web service methods through a partner Class Library, and take a reference on that Class Library
  • Make some modifications to Microsoft.Common.targets

In fact there is an easier way, which is similar to my last blog post. By adding the following information to your project file, the XmlSerializers assembly will start getting published with your application:

 <Target Name="BeforePublish"> 
  <CreateItem Include="%(SerializationAssembly.FullPath)" Condition="'%(Extension)' == '.dll'"> 
    <Output TaskParameter="Include" ItemName="_SGenDllsRelatedToCurrentDll" /> 
  </CreateItem> 
</Target>

Once again, BeforePublish is pre-populating some items to include some information for the ClickOnce manifest generation. In this case, the _SGenDllsRelatedToCurrentDll items are used by the ResolveManifestFiles task to figure out what should be published. The definition of SGenDllsRelatedToCurrentDll in Microsoft.Common.targets only picks up on SGen Dlls from referenced projects, but misses the XmlSerializers from the exe project (which is why the first work-around mentioned above will work). Making this change allows the XmlSerializers to be picked up, and you can even set properties on them in the Application Files dialog.

Note: This problem existed in both VS 2005 and VS 2008. This work-around doesn't work for VS 2005 (so far, I haven't been able to come up with something that didn't require modifying Microsoft.Common.targets (or re-defining GenerateApplicationManifest target)). Furthermore, this issue is fixed in VS 2008 SP1 (to be precise: it is fixed in .NET Framework 3.5 SP1). The fix taken in there is basically what I showed here: Including the SerializationAssembly in the _SGenDllsRelatedToCurrentDll items.