3
votes

I have the following configuration for a service which I've deployed to IIS. I can add a service reference for the service using the URL to the wsHttpBinding endpoint, but I cannot add it using the URL to the mexHttpBinding endpoint (and I want to switch the client to use the netTcpBinding)

The error I get is:

There was an error downloading 'http://ServerName:98/MyService.svc/mex'.

The request failed with HTTP status 400: Bad Request.

Metadata contains a reference that cannot be resolved: 'http://ServerName:98/MyService.svc/mex'.

Metadata contains a reference that cannot be resolved: 'http://ServerName:98/MyService.svc/mex'.

<system.web>
  <compilation debug="true"
               targetFramework="4.0" />
  <customErrors mode="Off"/>
</system.web>

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="netTcpBinding_MyService" />
    </netTcpBinding>
    <wsHttpBinding>
      <binding name="wsHttpBinding_MyService"
               maxBufferPoolSize="2147483647"
               maxReceivedMessageSize="2147483647" />
    </wsHttpBinding>
  </bindings>
  <services>
    <service behaviorConfiguration="ServiceBehaviour"
             name="MyService.MyService">
      <endpoint address=""
                binding="wsHttpBinding"
                bindingConfiguration="wsHttpBinding_MyService"
                name="MyServiceEndpoint"
                contract="MyService.IMyService" />
      <endpoint address="net.tcp://ServerName:198/MyService.svc"
                binding="netTcpBinding"
                bindingConfiguration="netTcpBinding_MyService"
                name="MyServiceNetTcpEndpoint"
                contract="MyService.IMyService" />
      <endpoint address="http://ServerName:98/MyService.svc/mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
      <host>
        <baseAddresses>
          <add baseAddress="http://ServerName:98/" />
          <add baseAddress="net.tcp://ServerName:198/" />
        </baseAddresses>
      </host>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="ServiceBehaviour">
        <serviceMetadata httpGetEnabled="true"
                         policyVersion="Policy15" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        <serviceCredentials>
          <windowsAuthentication includeWindowsGroups="true"
                                 allowAnonymousLogons="false" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
  <modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

The weirdest thing is that this configuration is copied almost verbatim from another service that I configured and deployed and I was able to successfully add a service reference to the client using the mexHttpBinding endpoint. Configuration for the original service is like this:

<system.web>
    <compilation debug="true"
                 targetFramework="4.0" />
    <customErrors mode="Off"/>
  </system.web>

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBinding_MyOtherService" />
      </netTcpBinding>
      <wsHttpBinding>
        <binding name="wsHttpBinding_MyOtherService"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647" />
      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="ServiceBehaviour"
               name="MyOtherService.MyOtherService">
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="wsHttpBinding_MyOtherService"
                  name="MyOtherServiceEndpoint"
                  contract="MyOtherService.IMyOtherService" />
        <endpoint address=""
                  binding="netTcpBinding"
                  bindingConfiguration="netTcpBinding_MyOtherService"
                  name="MyOtherServiceNetTcpEndpoint"
                  contract="MyOtherService.IMyOtherService" />
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  bindingConfiguration=""
                  name="MyOtherServiceMexHttpBindingEndpoint"
                  contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://ServerName:97/" />
            <add baseAddress="net.tcp://ServerName:970/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <serviceMetadata httpGetEnabled="true"
                           policyVersion="Policy15" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <windowsAuthentication includeWindowsGroups="true"
                                   allowAnonymousLogons="false" />
          </serviceCredentials>
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

As you'll notice, the only relevant differences in the configurations is the addresses for the netTcpBinding endpoint and the mexHttpBinding endpoint. Originally, I started with them both empty, but as I've been playing about trying to get it to work I added explicit addresses in.

Also, both service are configured the same in IIS, i.e. net.tcp bindings are enabled and configured on the relevant ports. They are also each running separate sites and separate app pools on the same server (and both app pools are running under the same identity).

Any help would be appreciated, thanks.

2

2 Answers

2
votes

Solved it. We have a Web.{Environment}.config for each environment we deploy to and the correct config was not being copied over the Web.config at build time because of a file lock (probably not being checked out of TFS) on Web.config...

One of those things I should really have checked first, but when it had always been working previously and then suddenly broke without warning I never thought to check.

1
votes

When using service in IIS you cannot set absolute URL in the endpoint configuration. Root URL is controlled by IIS and it follows common structure of Web Site (specifies port)/Web Application/Virtual Directory/SvcFile. You can only specify relative part of address specified after .svc file.

Setting full absolute address and base addresses is only for self hosted scenarios.

Even if you add service reference using wsHttpBinding endpoint you should still be able to switch it to netTcpBinding endpoint because that endpoint should be described in your WSDL (if you remove those absolute addresses). Both endpoints should be configured in your client's configuration file. Then you will just need to pass name of the endpoint configuration to constructor of service stub (WCF proxy).