If you know how *RelyBindings of Service Bus works or have at least an idea how they could work, it is clear, why service hosted with these family of bindings “cannot” be hosted in IIS.
The original design of IIS relies on almost philosophical assumption that there is some client out there which request some resource by sending a message. IIS receives the request/message, locates requested resource, performs some action in pipeline chain and returns the response.
If you understand why this topic is an issue and you have IIS 7.5 and AppFabric installed just jump over to topic Echo Service Sample.
What is the problem at all?
This concept has been existing for a while, as WCF came into IIS for first time. By using of WebServiceHostFactory, which is defined in SVC-files all seemed to be fine. The client sent the request to SVC-file, and WebServiceHostFactory has initialized the service.
The problem with *RelayBindings of Service Bus is, that they do not listen for incoming messages as typical service listeners do. Rely bindings in fact send message to Service Bus and wait on response.
So, and what is wrong with this?
The problem is that the client who sends the message will never send the message to SVC file. As a result of this design, the WCF service hosted on Rely Bindings will never be initialized.
If you like here is one interesting discussion about this.
Fortunately since IIS 7.5 (delivered with Windows 7 and Win Srv 2008 R2), there is a feature called Auto-Start. This is ability of a pool to be in so called mode Always-Running. More about this here.
This feature is very powerful and in context of WCF activates channels before any message arrives.
For all of you who do not exactly know what this does mean, here is a short explanation.
When you have a console application which should host the service you will typically call Open to activate the channel.
{
. . .
host.Open();
}
In typical IIS scenario this is done with help of WebServiceHostFactory, but when the message arrives.
If your service is hosted in IIS 7.5 and its pool is set on always-running the method Open() is called immediately after the pool is initialized. In other words, you do not need to wait on message to get the service initialized.
This is exactly the feature which *RelyBindings need.
How Windows Server AppFabric can help?
To make usage of Always-Running feature of IIS 7.5 you have to implement so called Service Auto Start Provider. This is in case of WCF services not very easy task. The good thing is that WIndows Server AppFabric has such provider out of the box. More over, AppFabric provides a powerful GUI, which can be used for configuration.
The ultimate solution with AppFabric looks very simple:
1. Implement the service and setup a site for it in IIS.
2. Enable Auto-Start by using of AppFabric
You will probably not believe me, but this is all (more or less). Otherwise it would be too boring. :)
Prerequisites
To make this working be sure that you have to have IIS 7.5.
Be also sure that you have installed Windows Server AppFabric.
And finally install following two patches: Patch 1 and Patch 2. First patch will allows you to use Service Bus configuration elements (transportClientEndpointBehavior and serviceRegistrySettings), because they are not defined by IIS set of schemas stored in C:\Windows\System32\inetsrv\config\schema. Without of this patch you cannot use AppFabric UI in this demo. The second one fixes one bug with auto-starting in multiple pools.
I took the existing ExchoSample solution and converted it in VS 2010. During conversion I set up both projects in solution (client and service) to .NET Framework 4.0. Thanks to Wade Wagner I just jumped in folder C:\Program Files (x86)\Windows Azure platform AppFabric SDK\V1.0\Assemblies\NET4.0 and executed RelayConfigurationInstaller.exe without of any change in config file.
This simple program just append few entries in machine.config file in folder C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config:
Echo Service Sample
To demonstrate this I used EchoService found in WindowsAzureAppFabricSDKSamples. I took the existing ExchoSample solution and converted it in VS 2010. The goal here is to prepare this solution to be hosted in IIS/AppFabric.
Now, I added the new project of type Asp.Net Empty Application and added EchoContarct.cs and EchoService.cs as linked files. I added them as linked files to demonstrate that I didn’t perform any change in the service. Following picture shows the solution.
The project with name “Service” will not be used in this demo.
Finally I setup hosting in IIS (in project properties panel of VS-IDE):
The ServiceIis will be hosted in IIS and Client will play a role of consumer. All we need to do is to prepare the configuration. This is the whole configuration of service model you need.
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<serviceActivations>
<add relativeAddress="ExchoService.svc"
service="Microsoft.ServiceBus.Samples.EchoService, ServiceInIis,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</serviceActivations>
</serviceHostingEnvironment>
<services>
<service name="Microsoft.ServiceBus.Samples.EchoService">
<endpoint address="sb://dobric.servicebus.windows.net/EchoService/"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="netTcpRelayBinding" behaviorConfiguration="myBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="myBehavior">
<transportClientEndpointBehavior credentialType="SharedSecret">
<clientCredentials>
<sharedSecret issuerName="******" issuerSecret="******" />
</clientCredentials>
</transportClientEndpointBehavior>
<serviceRegistrySettings
displayName="Damir's Echo Service hosted in IIS with
Windows Server AppFabric"
discoveryMode="Public">
</serviceRegistrySettings>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
First, under serviceHostingEnvironment I used file-less activation. Because the project does not contain the SVC file, I added service activation element, which would allows me to send request like: http://localhost/EchoService.svc . One could ask now, why do we need this service at all if the activation is not performed my sending of the message to that service?
The answer the client does not need it, but AppFabric. If you want to be able to set the service for message-less activation AppFabric has to know that the service exist.
In AppFabric dashboard click on Services as shown at picture below:
At this point I could select Configuration (right mouse click on service) and set up Auto-Start:
In my picture Auto-Start is disabled, because I enabled Auto-Start on Application level for all services which I will possibly host in this application. Here is where I did it. I selected my Application (ServiceInIis) and opened configuration dialog whown at the next picture:
Enable means Auto-Start for all services. Custom means, you will need to select a wanted service (like in previous picture). This is useful if not all services in application have to be Always-Running.
After you apply this change, AppFabric UI will setup the pool of the application to Always-Running.
In application host config file C:\Windows\System32\inetsrv\config\applicationHost.config this looks like:
<add name="MyPool" autoStart="true" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" />
After you apply changes open the following address in browser: https://dobric.servicebus.windows.net/
This is the address where your service will be hosted. If all worked fine you will see following in browser:
Hope this helps.
Damir
Posted
Aug 01 2010, 01:16 AM
by
Damir Dobric