Add service reference when using netTcp binding - wcf

I have a WCF service that I tested by copying its interfaces to a sample client project.
Now I want to work properly by adding a service reference.
The service is hosted in windows hosting (using installUtil).
The service has 2 projects - externals (interfaces + datacontracts) and internals (implementations).
For some reason it didn't have an app.config so I added one manually:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ExecutionService" behaviorConfiguration="Default">
<endpoint name="TCPEndpoint" address="" binding ="netTcpBinding" contract="Externals.IExecutionService"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Trying to add a service reference from my sample client causes the following error:
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:3040/ExecutionService/Externals.IExecutionService'.
There was no endpoint listening at net.tcp://localhost:3040/ExecutionService/Externals.IExecutionService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
If the service is defined in the current solution, try building the solution and adding the service reference again.
I saw here that there's no need in app.config.
I'm a bit confused and I'm a beginner with WCF.
How can a nice WPF app reference my service? I want the service to be windows hosted and I don't want to drag dlls with me.
Edit
I added a metadata endpoint and my appconfig now looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ExecutionService" behaviorConfiguration="Default">
<endpoint name="TCPEndpoint"
address=""
binding ="netTcpBinding"
contract="Externals.IExecutionService"/>
<endpoint address="mex"
binding="maxHttpBinding"
contract="Externals.IExecutionService"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I tried adding a service reference by using net.tcp://localhost:3040/ExecutionService, net.tcp://localhost:3040/ExecutionService/Externals and net.tcp://localhost:3040/ExecutionService/Externals/IExecutionService and I'm still getting the same error.

You need to do:
maxHttpBinding -> mexTcpBinding - you cannot use mexHttpBinding on net.tcp endpoint (and it's mex not max)
the contract for mex endpoint must be IMetadataExchange - as you want to have service metadata available through this endpoint
httpGetEnabled="false" as there will be no http endpoint to get metadata from
When I was testing the solution in a simple console host I needed to change name in <service> tag to Externals.ExecutionService (but this depends on how you instantiate the service)
Then your service reference will be available at: net.tcp://localhost:3040/ExecutionService/mex
as base address is net.tcp://localhost:3040/ExecutionService and the relative address for the mex endpoint is set to mex
Final app.config is below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Externals.ExecutionService" behaviorConfiguration="Default">
<endpoint name="TCPEndpoint"
address=""
binding ="netTcpBinding"
contract="Externals.IExecutionService"/>
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:3040/ExecutionService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
For a quick test if the configuration is correct I used console host app as a service host.
Program.cs:
using System;
using System.ServiceModel;
namespace Externals
{
class Program
{
static void Main(string[] args)
{
var sh=new ServiceHost(typeof(ExecutionService));
sh.Open();
Console.WriteLine("Service running press any key to terminate...");
Console.ReadKey();
sh.Close();
}
}
}
Run the console app and try to add service reference to your project through net.tcp://localhost:3040/ExecutionService/mex.

At first glance, you've forgotten Metadata Endpoint

Change this:
<endpoint address="mex"
binding="maxHttpBinding"
contract="Externals.IExecutionService"/>
To:
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange"/>
Notice it's not maxHttpBinding but mexTcpBinding, you had typo as well there.

Related

Unable to view WCF Mex EndPoints output in Web Browser

I am new to WCF and trying to understand Mex endpoints. I have created a testservice. Its working fine and I am able to view WSDL output from URL= "http://myweb.com:8000/testservice" as well using "URL" or "URL?wsdl".
However, I am getting 400 Bad request while browsing "URL/mex" in browser. I set httpGetEnabled="false" and then I am also able generate proxy class using svcutil as well.
Could you please advise why I am not able to veiw mex endpoint output in web browser. Below is the config file:
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="HelloTest.testservice" behaviorConfiguration="serviceBehaviour">
<endpoint binding="basicHttpBinding" contract="HelloTest.Itestservice" address="HelloTest">
</endpoint>
<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://myweb.com:8000/testservice"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true"></serviceMetadata>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

WCF - convert HTTP to Named Pipe

Guys I've been looking at a ton of blogs, SO posts this week and I am still unsure as to how I convert my WCF service from HTTP bindings to using Named Pipes.
I think there are different ways to do it, but I am using the web.configs and using a service reference in my code.
Rather than detail everything here I've tried, can I ask this question?
What are the steps I need to take to go from HTTP Binding to Named Pipes?
Do I need this MEX thing I see mentioned in (some) blogs/SO posts?
I know I need to set IIS to enabled protocols: net.pipe... and that IIS Express doesn't support this (that took an afternoon!)
Some relevant code, what I have right now:
in IEmployeeData:
namespace Mobile.ServiceLayer {
[ServiceContract]
public interface IEmployeeData
{ ... }
Calling the WCF service:
string endpointConfigName = "BasicHttpBinding_IEmployeeData";
EmployeeSvcRef.EmployeeDataClient edc = new EmployeeSvcRef.EmployeeDataClient(endpointConfigName);
EmployeeSvcRef.EmployeeListResponse emp = edc.EmployeeList();
WCF service web.config:
<services>
<service name="Mobile.ServiceLayer.EmployeeData">
<host>
<baseAddresses>
<add baseAddress="http://localhost:62734/EmployeeData" />
</baseAddresses>
</host>
</service>
...
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
client web.config:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IEmployeeData" />
...
<client>
<endpoint address="http://localhost:62734/EmployeeData.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IEmployeeData" contract="EmployeeSvcRef.IEmployeeData"
name="BasicHttpBinding_IEmployeeData" />
Like I said I've looked at SO posts and blogs but there's always a piece of the puzzle missing it seems!
EDIT: Client web.config after wizard:
<endpoint address="net.pipe://localhost/EmployeeData.svc/" binding="netNamedPipeBinding"
bindingConfiguration="NewBinding0" contract="IEmployeeData"
name="" kind="" endpointConfiguration="">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName" />
</identity>
</endpoint>
Ok this is what I did. You may find it easier to use the built-in tools mentioned in Max's comments. Right click on a web.config and choose Edit WCF Configuration. Get the WCF service done first and, providing the endpoints are set up, running this on the client (right click it's web.config) will present you with a wizard.
SERVER WEB.CONFIG
Service name is the fully-qualified name of the interface e.g. Mobile.ServiceLayer.IEmployeeData
The base address changes to
net.pipe://localhost/EmployeeData.svc
. Notice the port number is removed and the .svc is present(!)
Create an endpoint, the contract being your interface and binding of type netNamedPipeBinding.
Add a second endpoint for MEX which is MetadataEXchange.
Set ServiceMetaData httpGetEnabled to false.
<system.serviceModel>
<services>
<service name="Mobile.ServiceLayer.IEmployeeData">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/EmployeeData.svc" />
</baseAddresses>
</host>
<!-- NetPipe -->
<endpoint
address=""
binding="netNamedPipeBinding"
contract="IEmployeeData" name="MyNetPipe" />
<!-- Mex (Net.Tcp / Net.Pipe ) -->
<endpoint name="EmployeeDataNetPipeMex" address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
CLIENT WEB.CONFIG
Remove the binding entry from 'basicHttpBinding'
Add the section with an entry named NetNamedPipeBinding_IEmployeeData
Inside 'client' add an endpoint with the address
net.pipe://localhost/EmployeeData.svc
the contract being the 'referencename'.'interface'
<bindings>
<basicHttpBinding>
</basicHttpBinding>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_IEmployeeData" />
</netNamedPipeBinding>
</bindings>
<client>
<endpoint address="net.pipe://localhost/EmployeeData.svc" binding="netNamedPipeBinding"
bindingConfiguration="NetNamedPipeBinding_IEmployeeData" contract="EmployeeSvcRef.IEmployeeData"
name="NetNamedPipeBinding_IEmployeeData" />
</client>

Hosting WCF service

I am following THIS link to create my wcf service and hosting through window service its is working fine but when i change my namespace from "Microsoft.ServiceModel.Samples" to "EE.ServiceProcess.ABC" and do changes accordingly in app.config my window service dont get start properly
my
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="EE.ServiceProcess.ABC.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/EEServiceProcessABCservice/service"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/EEServiceProcessABCservice/service -->
<endpoint address=""
binding="wsHttpBinding"
contract=" EE.ServiceProcess.ABC.ICalculator" />
<!-- the mex endpoint is explosed at http://localhost:8000/EEServiceProcessABCservice/service/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Can any one please suggest where am i going wrong?

WCF - Can't Generate Metadata/Implement MEX for NetMsmq Binding under IIS WAS?

I have been successfull in implementing NetTcp bindings and metadata under WAS but I am having a problem with the netMsmqBinding under WAS/IIS. In a nutshell, I can implement MEX for a Self Hosted NetMsmq binding application but not WAS/IIS. It seems like WAS is rejecting any of the addresses that I use where I can use any address in the self hosted app. In other words I can do this in self hosted:
<system.serviceModel>
<services>
<service name="Microsoft.Samples.MSMQTransactedSample.OrderProcessorService" behaviorConfiguration="OrderProcessorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples/service" />
</baseAddresses>
</host>
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesTransacted" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.Samples.MSMQTransactedSample.IOrderProcessor" />
<!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="OrderProcessorServiceBehavior">
<serviceMetadata httpGetEnabled="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="TransactedBinding">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
Hoever, when I try something similar in WAS, it says no endpoint lisening at address 8000. It won't host the metdata. Can someone help me get metadata or implement MEX for NetMsmq in WAS:
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="MsmqBindingNonTransactionalNoSecurity" exactlyOnce="false">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
<services>
<service name="Portal.LoadSim.Services.MsmqService" behaviorConfiguration="PortalServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/PortalLoadSimServices10/MsmqService"/>
</baseAddresses>
</host>
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/PortalLoadSimServices10/MsmqService.svc" binding="netMsmqBinding" bindingConfiguration="MsmqBindingNonTransactionalNoSecurity" contract="Portal.LoadSim.Shared.IMsmqService" />
<!-- the mex endpoint is exposed at http://localhost:8000/PortalLoadSimServices10/MsmqService/mex -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="PortalServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
You need to add URL access control for your services. This command should work for you:
netsh http add urlacl url=http://localhost:8000/PortalLoadSimServices10/MsmqService user="NT AUTHORITY\NetworkService" listen=yes
To delete the entry
delete urlacl url=http://localhost:8000/PortalLoadSimServices10/MsmqService
HTH
UPDATE: This is not the anwer to your problem. This is what you would do if you wanted to run the services as a self-hosted application and run it under non-standard account. Sorry I was getting it mixed up. I tried using your configuration on a sample application at home and found I had to do two things to get it to work - one, I have to rename the queue to the path and name of the svc file (e.g. PortalLoadSimServices10/MsmqService.svc) and rather than using the base address just browse to the svc file in your IIS host application. You might also need to modify the queue permissions so iis can access it correctly. Let me know if this solves your issue.

Adding Service Reference to a net.pipe service

I have started learning WCF and have created a few test http services successfully. Now, i was trying to create a self-hosted WCF service using net.pipe binding. Below is the configuration file for the service:-
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="MEX" name="InProcService.MyService">
<endpoint address="MyService"
binding="netNamedPipeBinding" bindingConfiguration="" contract="InProcService.IMyService" />
<endpoint address="Mex" binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/InProcService/" />
<add baseAddress="http://localhost:8001/InProcService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MEX" >
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Now in my host application, I am starting the service using:-
ServiceHost host = new ServiceHost(typeof(MyService));
host.Open();
Console.WriteLine("Service started");
host.Close();
The service starts correctly when this code is executed.
Now, when in my client application, I try to add the service reference to this running service, it is not able to find it. Is there something which I am not doing or doing incorrectly?
I would appreciate any help I can get on this.
Cheers,
Abhi.
The service is opened and closed after that. By the time you start the client the server is already closed. So Console.ReadKey() is required is requied before close.