Exposing a Metadata Exchange (MEX) Endpoint over TCP with an IIS-hosted WCF Service
A customer recently asked me what seemed to be a simple question: how can I expose a MEX endpoint over TCP for a service hosted under IIS. I found out that it wasn't as simple as I had originally thought. Here's what you need to do:
Configure or add a net.tcp binding in IIS. To do this open inetmgr (Internet Information Services (IIS) Manager). Select Default Web Site from the tree view on the right hand side of the window and then click Bindings.... under Actions on the left hand side of the window as shown in the following screen shot:
The Site Bindings dialog is displayed as shown in the following screen shot:
Verify that there is a net.tcp binding listed. If not click the Add... button, select net.tcp in the Type dropdown and under Binding information type a port number, a colon, and an asterisk (8080:*, for example).
If there is already a net.tcp binding, you can modify the port used by selecting the binding and clicking the Edit button. You will use this same port number for the endpoint address for your service.
Still inside of inetmgr, select the virtual directory of your service in the tree view on the left hand side of the screen and click Advanced Settings... under Manage Application on the right hand side of the screen.
In the Advanced Settings dialog, add net.tcp to the list of enabled protocols. Make sure you place a comma between http and net.tcp.
Now, in your service's configuration file add a net.tcp base address, at least one service endpoint using the netTcpBinding, a mex endpoint using the mexTcpBinding and a serviceMetadata behavior as shown in the following code:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="MyTcpService.Service1"
behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8080/MyTcpService"/> <=== Specify net.tcp base address
</baseAddresses>
</host>
<endpoint address="net.tcp://localhost:8080/MyTcpService" <=== Specify service endpoint with netTcpBinding
binding="netTcpBinding"
contract="MyTcpService.IService1"/>
<endpoint address="mex" <=== Specify MEX endpoint with mexTcpBinding
binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true"/> <=== Specify serviceMetadata behavior
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
To test this configuration I used the svcutil.exe commandline tool as follows:
svcutil net.tcp://localhost:8080/MyTcpService/Service1.svc
And sure enough svcutil generates the proxy and config file.
<
configuration>
<
system.web
>
<
compilation debug="true" targetFramework="4.0"
/>
</
system.web
>
<
system.serviceModel
>
<
services
>
<
service name="MyTcpService.Service1"
behaviorConfiguration="MyServiceBehavior"
>
<
host
>
<
baseAddresses
>
<
add baseAddress="net.tcp://localhost:8080/MyTcpService"
/>
</
baseAddresses
>
</
host
>
<
endpoint address="net.tcp://localhost:8080/MyTcpService"
binding="netTcpBinding"
contract="MyTcpService.IService1"
/>
<
endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange"
/>
</
service
>
</
services
>
<
behaviors
>
<
serviceBehaviors
>
<
behavior name="MyServiceBehavior"
>
<
serviceMetadata httpGetEnabled="true"
/>
<
serviceDebug includeExceptionDetailInFaults="false"
/>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
<
serviceHostingEnvironment multipleSiteBindingsEnabled="true"
/>
</
system.serviceModel
>
<
system.webServer
>
<
modules runAllManagedModulesForAllRequests="true"
/>
</
system.webServer
>
</
configuration
>