Friday, October 21, 2011

ServiceReference.ClientConfig build management in Silverlight projects

I’ve blogged a before for web.config transformations and how I would like to see them in other projects. While for Windows Azure cloud service project there is already similar feature implemented, I wonder why there is no out of the box support for other project types.

Here I will reveal the powerful, yet simple implementation of such transformation over your ServiceReferences.ClientConfig files. Thus you will no longer wonder what are your service endpoints, and which endpoint you are using. And this is not Windows Azure specific. It is relevant for any Silverlight project.

Just implement these simple steps:

1. Edit your .csproj file of the Silverlight application. Add the following block:

<UsingTask TaskName="TransformXml"

   
AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"
/>
   <
Target Name="BeforeBuild"
Condition="exists('ServiceReferences.$(Configuration).ClientConfig')">
     <!--
Generate transformed app config in the intermediate directory –
>    
<
TransformXml Source="ServiceReferences.ClientConfig"
      Destination="$(TargetDir)\ServiceReferences.ClientConfig"
      Transform="ServiceReferences.$(Configuration).ClientConfig"
/>
     <!--
Force build process to use the transformed configuration file from now on. –
>
     <
ItemGroup
>
       <
Content Remove="ServiceReferences.ClientConfig"
/>     
<
ContentWithTargetPath 
Include="$(TargetDir)\ServiceReferences.ClientConfig"
>      
<
TargetPath>ServiceReferences.ClientConfig</TargetPath
>
       </
ContentWithTargetPath
>
     </
ItemGroup
>
   </
Target>

right after:

 <Import 
Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />

2. Add new XML file to your project. Name it ServiceReferences.[BuildConfiguration].ClientConfig. Where [BuildConfiguration] can be the name of *any* build configurations you have defined for your project. The default build configurations are “Debug” and “Release”, but you may add as many as you like, to suit your development/testing/staging/live environments. Remember to set “Build Action” to “None”, and “Copy to output directory” to “Never”:



3. Add the required content in that custom file. For example, if you want to just change an endpoint for a service, you will have something like this (ServiceReferences.Debug.ClientConfig):

<?xml version="1.0" encoding="utf-8"?>
<
configuration
  xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
>
     <
system.serviceModel
>
         <
client
>
             <
endpoint 
address="http://127.0.0.1:81/DummyService.svc"
xdt:Transform="SetAttributes"
/>
         </
client
>
     </
system.serviceModel
>
</
configuration>

For more information on XML transformations supported, please take a look at the MSDN documentation for Web.Config transformations. Do not panic! The documentation is for “web.config” transformations, but these are just XML transformations that can transform any XML file Winking smile

10 comments:

Mike said...

This is exactly what I'm looking for. Thanks for sharing!

Nick said...

This is really good, but there's a problem with it. Because the target is BeforeBuild, it will fail building if the clientconfig doesn't yet. If you delete your bin folder, you will get a failed build. The target bin has to exist first and it will work.

Nick said...

This is really good. This article fixes a couple issues I had with this method: http://stackoverflow.com/questions/7360533/dynamic-endpoints-in-servicereferences-clientconfig

Anton Staykov said...

@Nick, it will not fail, because there is condition for the target, which first checks the existence of desired transorming clientconfig. Also, ClientBin in the hosting web app has nothing to do with the clientconfig file, as this file is part of the XAP file.

Rodrigo S. Teixeira said...

Thanks for your tips, it was really helpful. I was going to give up using Transformation only because Silverlight application compatibility.

Rodrigo S. Teixeira said...

Thanks for your tips, it was really helpful. I was going to give up using Transformation only because Silverlight application compatibility.

Rodrigo S. Teixeira said...

Thank your for your tip. It was really helpful. I was going to give up using Transformation only because Silverlight application compatibility. You just save my work!

Anonymous said...

Actually, you can modify the ServiceReferences.clientConfig and change the endpoint to "../yourservice.svc"

see MSDN

davron12 said...

Thank you! This is exactly what I was looking for. Now if only I could get that ServiceReference.Release.ClientConfig files to show up under the ServiceReference.ClientConfig file, the the Web.configs do...

IvanP said...

in case you dont want to be dependent on vs v10 use token, so the usingtask element would look like