Introduction
In this tip, I will demonstrate how you can deploy your WCF service(s) to Internet Information Services (IIS) automatically as part of your build process. I do this using an Nant script that invokes the necessary MSBUILD
commands. Before the WCF service is deployed, I make a backup of the currently deployed service, so should anything not work as expected, I can always get back to where I was previously.
Background
It is assumed that the reader is familiar with Nant syntax and MSBUILD
. It is also assumed that the reader is familiar with hosting applications under IIS. I have used Visual Studio 2010.
An Overview of the Process of Deploying your WCF Service
When deploying an application to IIS, the same (or similar) process that I am outlining here for a WCF service library is the same had we been deploying a web application. Fundamentally, we are publishing an application that is hosted under IIS, so it makes sense that the steps are broadly similar.
When you deploy your WCF service, you need to deploy the following files to your deployment folder.
- The WCF service endpoint(s) e.g. myServiceEndpoint.svc
- The WCF service web.config
- The WCF service assembly e.g. myService.dll
We will create the web.config and service endpoint(s) files using Visual Studio, and then add these files to our Visual Studio solution. Our build script will then refer to them when it deploys the WCF service to IIS. The assemblies will get created by the build script when it builds the WCF service. As the service endpoint(s) and web.config change less frequently than the assemblies, then deploying the files in this way is ideal.
Just to be clear, the service endpoints and web.config that get deployed using this process are created once and then added to your solution, so the build process does NOT create these. Only the WCF service assemblies get generated each time the build script is executed.
Your WCF assemblies should be in a sub-folder called bin. The following screenshot shows the folder structure of a typical deployed WCF service.
As can be seen in the screenshot, it is perfectly possible to have multiple endpoints and assemblies, but you should have only one web.config file.
The steps involved in deploying your WCF service automatically from an Nant build script are:
- Create the initial deployment files (the service endpoint (.svc) file(s) and web.config) and add these to your Visual Studio project
- Update your project file (.csproj) by adding the
Microsoft.WebApplication.targets
target - Update your Nant build script with the required
MSBUILD
target for publishing a WCF service
Create the Initial Deployment Files
You will firstly need to create the service endpoint(s) and web.config file that are required by your deployment. Once you have created these, you then need to add them to your Visual Studio project.
To create the service endpoint(s) and web.config, you achieve this by publishing your WCF service for the first time using Visual Studio.
- Add a new folder to your solution and call it something meaningful. I have called mine DeploymentFiles in the example below.
- Open your WCF solution in Visual Studio and right-click on the main project (the one containing the WCF service implementations).
- From the context menu, select Publish. Ensure your newly added folder is selected in the dialog box.
- When finished, you can safely delete the bin folder that is created.
You will need to repeat this step each time you update the web.config or add a new service endpoint.
Add the Deployment Files to Your Visual Studio Solution
The screenshot below shows the folder structure of a Visual Studio solution which includes a folder called DeploymentFiles which contains the web.config and service endpoints (.svc files) that were created in the above step. The folder and files have been added to the Visual Studio solution.
Update your Project File
To ensure that your project file (.csproj) is capable of publishing your WCF service, you need to ensure that it contains the necessary MSBUILD
target. The target that performs the publishing task is Microsoft.WebApplication.targets
.
- If you have the project open in Visual Studio, then you will need to close it before proceeding.
- Open the .csproj file in a text editor such as Notepad and add the following line:
<Import Project=
"$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
This will add the necessary target to your project and ensure that it is capable of publishing. Without this statement, you will receive the error message The target “_WPPCopyWebApplication” does not exist in the project when you attempt to publish it.
Add a New MSBUILD Target to Your Build Script
Now that your Visual Studio solution contains the necessary deployment files and has the capability to publish, the only remaining step is to update your Nant build script with the necessary MSBUILD
target.
The MSBUILD
command for publishing a WCF service (and also a web application) is given below:
<MSBuild Projects="BusinessTier.csproj" Targets="Rebuild;_WPPCopyWebApplication"
Properties="WebProjectOutputDir=DeploymentFiles;UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False" />
Note the target specified is _WPPCopyWebApplication
. This is the target that actually publishes your WCF service. It invokes the Windows Publishing Pipeline (WPP) to accomplish this.
Now that we have the syntax of the necessary MSBUILD
command, we can now update our Nant build script so that we can automatically deploy our WCF service to IIS.
<target name="CopyToDeployFolder">
<echo message="Task execution started at : ${script::format-to-string(datetime::now())}" />
<property name="built.deploy.dir" value="C:\WCFServices" />
<property name="built.deploy.backup.dir" value="${built.deploy.dir}.Backup" />
<mkdir dir="${built.deploy.backup.dir}"
if="${not directory::exists(built.deploy.backup.dir)}"
failonerror="true"
verbose="${verbose}" />
<copy todir="${built.deploy.backup.dir}" overwrite="true" verbose="true">
<fileset basedir="${built.deploy.dir}">
<include name="**/*" />
</fileset>
</copy>
<property name="build.item" value="BusinessTier.csproj" />
<property name="config.type" value="Release" />
<property name="target" value="_WPPCopyWebApplication" />
<msbuild project="${build.item}" target="${target}" verbose="${verbose}" failonerror="true">
<property name="Configuration" value="${config.type}" verbose="${verbose}" />
<property name="WebProjectOutputDir" value="${built.deploy.dir}" verbose="${verbose}" />
<property name="UseWPP_CopyWebApplication" value="true" verbose="${verbose}" />
<property name="PipelineDependsOnBuild" value="false" verbose="${verbose}" />
</msbuild>
<copy todir="${built.deploy.dir}" overwrite="true" verbose="true">
<fileset basedir="DeploymentFiles">
<include name="**/*" />
</fileset>
</copy>
<echo message="Task execution finished at : ${script::format-to-string(datetime::now())}" />
</target>
Summary
Automatically deploying your WCF application as part of your build process simplifies the entire process by removing the need for the developer to have to remember to perform the step manually. If done as part of your build process, then it is performed in a consistent manner each time your build script is executed. Feel free to leave a comment if you would like me to further elaborate on anything within this tip.