Category name:WCF

Deploying WCF Services using Web Deploy

More than two years ago I wrote a blog post about deploying WCF services using a Web Setup project. Back then it wasn’t an easy task to get services deployed using it. Especially the UI customization of the installation wizard dialog gave me some headache, moreover because they were difficult to test and debug.

As also mentioned in the comments of that post, we now got Web Deploy! So I decided it was about time to rewrite the blog post using the same requirements but then with Web Deploy. Let’s see how much easier it became.

A small revisit of the requirements as formulated in the other blog post:

  1. support deployment of the WCF artifacts
  2. be able to be deployed to whatever web site is available on the server
  3. be able to set ASP.NET security to NTLM
  4. be able to gather service settings during setup
  5. be able to change custom AppSettings in the web.config according to the settings

Web Deploy is available for Visual Studio 2005/2008, but I’ll be focusing on Visual Studio 2010. The approaches of the Web Deploy and Web Setup are different. In Web Setup the output was an MSI which could be run by a system administrator. The Web Deploy approach is focused on IIS as the host of the web application or service. This means the output is no longer an MSI but a (ZIP) package that can be imported in IIS or IIS Express or installed using the MSDeploy command line tool.

What are the typical steps to take to deploy a web application or WCF service using Web Deploy from Visual Studio?

First, select the ‘Publish’ option on the project context menu.

A profile page will show up in which you can specify which publish method to use. The options are:

  • Web Deploy
  • FTP (File Transfer Protocol)
  • File system
  • FPSE (FrontPage Server Extensions)

Also define a profile name, the server to deploy to and the name of the web application or WCF service. Next click ‘Publish’ and the artifacts are deployed to the target IIS server and site/application.

This covers requirement 1: support deployment of the WCF artifacts

As a side step: if you want to deploy to a remote server, you might run into a few challenges. The Web Deploy is a client/server installation so you need to correctly setup your (IIS) server in order for it to receive the deployment request. If you want to know more, take a look at these posts:

Requirement 2 is: be able to be deployed to whatever web site is available on the server

In the previous step the target web site was defined in Visual Studio, but that should be dynamically changeable when a system administrator runs the package on for example a production environment.

First the package must become portable so it can be installed on a different server, and the next step is enabling the system administrator to pick the website to deploy the service to.

To create a package there are 2 options you can use:

  • Visual Studio
  • IIS (use the Export Application functionality, which is a topic by itself and not covered here)

In Visual Studio take from the project context menu the option ‘Package/Publish Settings’ to define how the package looks like and then ‘Build Deployment Package’ to actually build the package.

Important settings here are the location of the package, which is a ZIP file, and the target location of the WCF service on the IIS server. Next select ‘Build Deployment Package’ to create it.

Now the package has been build, it is interesting to see what’s in it. Browse to the folder specified in the ‘Package/Publish Settings’ folder to find the files below.

The package consists of:

  • CMD file
    • This batch file can be used to deploy the package to a server without having to access IIS via the administration console. It uses the command line tool MSDeploy to deploy the package using Web Deploy. Suitable for unattended and/or bulk installations
  • Readme file
    • Interesting file describing all options for the CMD file. One very interesting one is the /T option, which calls msdeploy.exe with the “-whatif” flag, which simulates deployment. This does not deploy the package. Instead, it creates a report of what will happen when you actually deploy the package. Very useful for testing purposes!
  • Parameter file
    • This file contains the parameters that are defined for this service and are extracted from the project file (DeployIisAppPath element) during packaging. This file contains by default only one item, see below. Here we immediately notice that this is the value we need to cover requirement 2.
  • Manifest file
    • This file is not used during deployment, but during generating the package. It contains provider settings and like you can see below some security related entries for the IisApp and setAcl provider.
  • ZIP package
    • Contains the service to deploy, including configuration, binaries and other artifacts. If you open the ZIP you’ll see all kinds of configuration files that are used during import of the application

For now let’s see how to install the package onto a different server based on the package. First open IIS and select the web site you want to import the web application or WCF service to.

It is out of scope to describe all wizard dialogs but at a certain time you’re asked to specify the application:

In here you can define the destination application and if it doesn’t exist, it will be created for you. This is out-of-the box functionality, but nothing different from the Web Setup approach. Anyhow, this is what we need to fulfill requirement 2.

Requirement 3 is: be able to set ASP.NET security to NTLM

By default the security is set to anonymous access, so we need to change that to windows authentication.

At first this didn’t seem like a big deal, because I expected it to be some parameter or manifest setting, but the more I read on the internet the more I got worried. There is a lot to find about Web Deploy and Windows Authentication, but that mostly relates to using Windows Authentication to connect to the Web Deploy server (up to adding keys to the registry), and not about changing the authentication of a deployed WCF service or web application.

So far I haven’t found an easy way to change the authentication of a deployed WCF service or web application. What I did find was a thread in the IIS Forums about specifying the authentication in the web.config, but in order for that to work the applicationHost.config must be changed to allow overrides. That config file is maintained by the system administrator and I can understand why the system administrator should know about deployment scripts that change the authentication. On the other hand, having a WCF service with Windows Authentication is not that uncommon.

Another option that was mentioned in this thread refers to running a command file which can be added to the manifest file. This command file will probably contain some VBScript to change the authentication after the package has been installed. The difficult thing here is knowing in which web site the WCF Service has been deployed…..

I really hope I overlooked something, so if somebody knows how to do this please leave a comment! Thanks in advance!

Requirement 4 and 5 will be discussed combined: “be able to gather service settings during setup” and “be able to change custom AppSettings in the web.config according to the settings”

Like we’ve seen before, there is a parameters file. This file can be customized from within Visual Studio to make it possible to change the UI the system administrator will see. For this example I’ll demonstrate what it takes to change the value of a custom AppSetting in the web.config. This will be changed from within the UI of IIS. The value to change is a key named ‘Test’ in the AppSettings section of the web.config.

First, add an XML file to your project called “Parameters.xml”, this will contain the parameters the UI will show. This is a different file from the ‘SetParameters.xml’ file we saw earlier; that one is used with the command line option and this one with the IIS import.

Next add this piece of XML. By the way, this is a good resource to learn more about parameters in Web Deploy.

This piece describes two things:

  • It defines a parameter with a description to show up in the UI and a default value which will be filled in.
  • It defines where the value, read from the UI, should be applied. In this case it is targeted at the web.config file and the XPath points to the AppSettings key ‘Test’.

Building a package from this and importing it in IIS results in the following UI:

As you’ll notice the name and description are displayed nicely, together with the default value. When the value is changed, it will be changed in the web.config when the wizard is finished.

You can imagine the possibilities of this approach. It is very easy to change the UI and set values for example in the web.config without having to code it.

So, did it actually became easier to deploy WCF services? Yes and no. Obviously it is much easier to customize the UI and perform all kinds of actions while deploying, but on the other hand it seems very difficult to perform some common task like changing the authentication of a web site. Like mentioned before, I hope someone will leave a comment with a clarification on the authentication issue.

Anyhow, there is much more you can do with Web Deploy then is covered in this blog post. Please find below useful spending of your spare time.

Didago IT Consultancy

Deploying a WCF Service using a Web Setup Project

With this blog post I hope I can save others some time and besides that it is also nicely stored for me in case I need it again.

For my current project I’m building some WCF services. One of the requirements is to have a MSI to hand-over to the system engineers for deployment.

The setup should:

  1. support deployment of the WCF artifacts
  2. be able to be deployed to whatever website is available on the server
  3. be able to set ASP.NET security to NTLM
  4. be able to gather service settings during setup
  5. be able to change custom AppSettings in the web.config according to the settings

While I’m familiar with Visual Studio Setup projects, I came across some interesting challenges.

Requirement 1 and 2 are easy. The regular Web Setup project is capable of doing that out of the box. If you add a Web Setup project to your solution and specify the “File System on Target Machine”. Put the svc and web.config in the “Web Application Folder” and the output of the WCF project to the “bin” folder. This will deploy your WCF service to the website you specify in the setup wizard.

filesystem[1]

One caveat however is to set the value of the Virtual Directory as it is shown by default when you run the setup. This is by default the name of your WebSetup project. In my case this was <company>.<division>.<Project>.<Subproject>.<Setup>

This is definitely not the virtual directory name you want to see in IIS. This cannot be changed in Visual Studio because it is not shown as a property, you need a text editor like Notepad. So open the project file of the WebSetup project: the ‘vdproj’ file. Search for “VirtualDirectory” and change the value to something suitable.

The 3rd requirement is a bit more difficult. By default the web services are installed with anonymous authentication so to change that, a step in the setup should be appended. After some searching I found out I had to add a so called custom installer. That is a class that inherits the System.Configuration.Install.Installer class. You can override the ‘Install’ and/or ‘Uninstall’ methods to add custom code to the installer.

So I added a CustomInstaller Class Library project to host the CustomInstaller class. Next step was how to modify the authentication of the just installed web service? This can be done using WMI or ADSI and I decided to go for WMI. I already did some things with WMI but now I needed to do more. Unfortunately the documentation is not very ‘user friendly’ and after some trying I decided to look for a ‘WMI query analyzer’ or something like that to get at least an overview of the possible queries. I was very happy to find the WMI Explorer by KS-Soft. It is a free download that exactly does what I needed: give an overview of what is out there regarding classes, instances and properties. A very valuable tool.

I needed a query to access the properties of the WCF service. Therefore I needed to query the “IIsWebVirtualDirSetting” class, based on the virtual directory of my WCF service. But how to get the virtual directory name? The system engineer can change that value so we need to ask the runtime to get it.

By default the runtime keeps some variables that you can retrieve in your code. For WebSetup projects that are:

  • TARGETVDIR – virtual directory to be created
  • TARGETSITE – website where the virtual directory is to be created (site must exist), example: "/LM/W3SVC/1
  • TARGETAPPPOOL – application pool to use (must exist, it won’t be created)

If you supply the parameters (to which I will come back later), you can access the runtime context to get the variables using Context.Parameters. The code below does that and more.

wmicode[1]

I create a ManagementScope for “\localhostrootMicrosoftIISv2” to connect to the local IIS instance. Next I query for the IISWebVirtualDirSettings of my WCF service to get access to the properties. This query is based on the website name and the virtual directory. If there are multiple websites in IIS, we have to get the correct one.

With the following code we can iterate over the result (which should only contain one record) and set the property.

wmicode2[1]

So now the code is in place to set the authentication, but how do these parameters get into the Context object? You have to specify a custom action to your project and the custom installer is the action you need to add.

setupcustomaction[1]

Then you can specify properties on the custom installer and they will end up in the Context object.

setupcustomaction2[1]

As you can see the parameter starts with ‘/’ and the value is in double quotes and square brackets if it is a variable which is gathered during the setup process in the wizard. You can also add plain text like I did with ‘localhost’ in this case. Warning: do think about the double quotes, if forgotten nothing works and there are no messages to tell you why!

Requirement 4 is simply extending the user interface. You can find a very good blog post here so I won’t cover that in detail.

Finally the 5th requirement: set some AppSettings values in the web.config

The blog post I just mentioned also describes how to modify web.config settings from a setup project. There is one difference to my situation and that is that I have to change the configuration file for a process I haven’t loaded the host of. So I cannot use the OpenExeConfiguration method of the ConfigurationManager class. Also the web.config specific method OpenWebConfiguration of the WebConfigurationManager class cannot be used.

Via WMI I was able to find the physical path of the web.config and I was almost thinking about using some XmlDocument class to read and process the settings when I found this forum topic.

It describes exactly what I need. I have to use the OpenMappedWebConfiguration method of the WebconfigurationManager class. Then I can still use the capabilities of this class to modify the settings without having to foul around with XML tags myself. With this in place it’s a piece of cake to change the settings.

modifywebconfig[1]

Looking back everything is very easy, as always, but I had a hard time finding the right information. Also I have my doubts about WMI over ADSI. It seems like the ADSI queries are more intuitively but I’m not sure about that.

If you have a better, easier, quicker or fancier solution, please let me know!

[WCF] Fault contracts

While setting up a default environment for WCF development, I thought it would be a good idea to also include something about fault contracts. A fault contract is an exception class the service can throw to the client containing specific exception information.


The steps to set this up on the service:



  • Create a class 


    • follow naming conventions like ending with ‘FaultContract’ like ‘DefaultFaultContract

    • add one or more properties to the class

  • Apply the FaultContract attribute in the interface to the requested method


    • [FaultContract(typeof(DefaultFaultContract))]

  • Throw the exception in the implementation


    • throw new FaultException<DefaultFaultContract>(new DefaultFaultContract(“Something went wrong”));

    • you can also add a FaultReason to inform the client about the circumstances

After the service is build, the client can be generated using the ‘Add service reference’, but that won’t be something new 😉
Now the custom exception class is also known on the client and can be caugth with:



  • catch (FaultException<SampleService.DefaultFaultContract> ex)

  • in ex.Detail you can find your custom fault contract

In Visual Studio it is possible to let the debugger break on unhandled exception. Normally something you want to happen, but in this case it is not a good idea. The debugger thinks that the exception thrown in the service is unhandled, so it breaks saying it found an ‘FaultException was unhandled by user code’ but in fact the exception is handled by the client.

[WCF] Great tools in SDK

While browsing the WCF SDK I found two great tools:



  • Microsoft Service Configuration Editor

  • Microsoft Service Trace Viewer

The configuration editor helps you with the confguration files that you need with WCF. It simplyfies editing those files significantly. By using a tool you also avoid typing errors and it is very easy for example to switch diagnostic information on or off.


With the tracing switched on, you can use the trace viewer to browse the actual log files produced. This tool shows all messages flowing and additional information about the messages like what the body of the message was and the duration of the message. With this tool it is easier to find out what is going wrong if you run into an error or unexpected behavoir.


Both tools can be found in the following SDK folder C:Program FilesMicrosoft SDKsWindowsv6.0Bin or you can download it here.

WCF: HTTP 404 when hosted in IIS

While playing with WCF I ran into someting when I wanted to host the service in IIS.


I created a ‘service.svc’ in a folder, added a web.config, created a bin folder to put the assembly in, and added a website to that folder in IIS. According to the MSDN documentation and several blogposts, that was enough to host the WCF service in IIS.


But when I tried to browse the service, I received an HTTP 404 error.


In the release notes of the .NET 3.0 framework I found the following, which I thought should solve the problem because it exactly describes my problem.


2.7.4 May not be able to web host WCF services if a pre-RC1 version of WCF was previously installed


If you installed a previous version of the .NET Framework 3.0 while IIS was installed, when you upgrade to the RTM version of the .NET Framework 3.0 you may have difficulty accessing WCF services that are IIS hosted using .svc files. On computers running Windows Server 2003, accessing an .svc extension from the browser may return a “404: Page Not Found” error. On computers running Windows XP, the .svc content may be displayed as plain text.

This is due to an issue with WCF script map registrations in a previous release.   


To resolve this issue


There are three ways to work around this issue:



  1. Download the unsupported tool, CleanIISScriptMaps.exe from http://wcf.netfx3.com/files/folders/product_team/entry5648.aspx. Run the tool from a command console without any arguments.
  2. Uninstall and reinstall IIS or re-create your Web sites:

    1. Uninstall IIS and reinstall it so that the IIS Metabase is refreshed. Then run the WCF install tool manually to re-register the WCF scriptmaps:
      “%windir%Microsoft.NETFrameworkv3.0Windows Communication FoundationServiceModelReg.exe” /r /y

    2. If you are running Windows 2003 Server, you may be able to resolve the problem by deleting the “Default Web Site” and re-creating it.

  3. Install .svc manually as a temporary workaround:
    You can run the following command to install .svc mapping manually. However, this refreshes the IIS Metabase for existing sites. “%windir%Microsoft.NETFrameworkv3.0Windows Communication FoundationServiceModelReg.exe” /s:W3SVC

After trying all this, still a 404. 🙁
What actually caused the problem was the fact that I forgot to mark the website as a .NET 2.0 website instead of a 1.1 site which is the default.