Windows Azure metadata issue when hosting service on multiple endpoints

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

When working with WCF you might get following exception:

The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the HttpGetUrl property is a relative address, but there is no http base address. Either supply an http base address or set HttpGetUrl to an absolute address.

Note that there are few different reasons why this can happen. Basically this exception is thrown when there is a mismatch between binding and  metadata url. For example you use binding with transport security (HTTPS) and HttpGetUri is setup to provide metadata at the HTTP address. However this is not my focus in this post.

I’m more interested to explain how to handle this error in the Windows Azure scenario.

Imagine you already have one service which is hosted on premise at “http://localhost:801/MyService/”. Following configuration shows MyServ ice which is hosted at that address. More over, the same service exposes an endpoint  hosted in Windows Azure AppFabric Service Bus. When you run the host, it will fail with exception shown above.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>

          <endpointBehaviors>
            <behavior name="sbBehavior">
              <transportClientEndpointBehavior credentialType="SharedSecret">
                <clientCredentials>
                  <sharedSecret issuerName="" issuerSecret="=" />
                </clientCredentials>
              </transportClientEndpointBehavior>
              <serviceRegistrySettings
              displayName="MyService for extranet users"
              discoveryMode="Public">
              </serviceRegistrySettings>
            </behavior>
          </endpointBehaviors>
                   
        </behaviors>
        <services>
            <service name="Service.MyService">
                <endpoint address="" binding="wsHttpBinding" contract="Service.IMyService" >
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>

              <endpoint  address="sb://myservice.servicebus.windows.net/ExtranetServices/MyService/"
                         contract="Service.IMyService"
                         binding="netTcpRelayBinding"
                         behaviorConfiguration="sbBehavior" />

                 <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:801/MyService/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>

 

The host will fail, because WCF 4.0 enforces using of default behavior for all services defined in the application. In this case this will be the service MyService. If you take a deeper look in configuration you will notice that this service has additional rely-binding. This binding exposes the service via Service Bus by using of TCP (netTcpRelyBinding). This cases the service to bind default service behavior for all endpoints. By enabling of metadata WCF internally combines base address of the service with address specified in the endpoint. When this happens, metadata cannot be enabled, because base address is HTTP and endpoint requires TCP (sb://).

To make this working change default behavior to named behavior and reference it by endpoint hosted on-premise:

            <serviceBehaviors>
                <behavior name="onPremise">
                    <serviceMetadata httpGetEnabled="true"
                                    
                                     />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>

            . . .

            <service name="Service.MyService" behaviorConfiguration="onPremise">
                <endpoint address="" binding="wsHttpBinding" contract="Service.IMyService" >
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>


Posted Mar 25 2011, 12:29 AM by Damir Dobric
Filed under: , , ,
developers.de is a .Net Community Blog powered by daenet GmbH.