I'm trying to expose an interface through NetNamedPipeBinding.
Here's what I do:
try
{
//load the shedluer static constructor
ServiceHost svh = new ServiceHost(typeof(MyClass));
var netNamedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
var netNamedPipeLocation = "net.pipe://localhost/myservice/";
svh.AddServiceEndpoint(typeof(IMyInterface), netNamedPipeBinding, netNamedPipeLocation);
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = svh.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
svh.Description.Behaviors.Add(smb);
// Add MEX endpoint
svh.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexNamedPipeBinding(),
netNamedPipeLocation + "/mex"
);
svh.Open();
Console.WriteLine("Service mounted at {0}", netNamedPipeLocation);
Console.WriteLine("Press ctrl+c to exit");
ManualResetEvent me=new ManualResetEvent(false);
me.WaitOne();
svh.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception");
Console.WriteLine(e);
}
The service starts ok, but when I create a new Visual Studio project and try to add a service reference at location net.pipe://localhost/myservice/, I get following error:
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.pipe://localhost/myservice/'.
Metadata contains a reference that cannot be resolved: 'net.pipe://localhost/myservice/'.
If the service is defined in the current solution, try building the solution and adding the service reference again.
If I substitute NetNamedPipeBinding for TcpBinding, the code works ok, and service reference can be added.
What should I change, so I can add service references in Visual Studio?
With var netNamedPipeLocation = "net.pipe://localhost/myservice/"; netNamedPipeLocation + "/mex" winds up being net.pipe://localhost/myservice//mex. Your AddServiceEndPoint call should be
svh.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexNamedPipeBinding(),
netNamedPipeLocation + "mex"
);
After removing the extra / I was able to connect to a local named pipe service hosted using your code without issue.
Related
I've got a strange problem: I have a wcf service which needs to be hosted by tcp protocol on a standalone console application.
I have created a new console app project and added a lib reference for my wcf project. The problem occurs when I want to configure and broadcast the host.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
MyServiceHost = new ServiceHost(typeof(ImyService), Uri);
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "");
var mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange),mexBinding, "");
ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
When it comes to open the host, I get this message:
The contract name 'IMetadataExchange' could
not be found in the list of contracts implemented by the service WcfService.Ser
vices.MyService. Add a ServiceMetadataBehavior to the configuration
file or to the ServiceHost directly to enable support for this contract.
Now that I have better time to check this.
First you need to get the service behavior from the host or create a new one and add it if not found.
Setting the HttpGetEnabled requires you to also ad a metadata uri to the baseaddresses.
Also it does not seem to matter if the metadata endpoint is named "mex", as long as all endpoints added have unique names. So you can't use empty string for both endpoints.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
var MetadataUri = new Uri("http://myaddress:8000/MyService");
var MyServiceHost = new ServiceHost(typeof(MyService), Uri, MetadataUri);
var serviceBehavior = MyServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (serviceBehavior == null)
{
serviceBehavior = new ServiceMetadataBehavior();
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
}
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "image");
I want to create a class that implementing 2 service contracts, and exposing 2 end-points on different ports (I get the ports as input to the program).
My question is very similar to this question, but I want two end-points each one on different port.
EDIT:
Using this code:
var aConnectionString = "http://localhost:8200/A";
var bConnectionString = "http://localhost:8201/B";
ServiceHost host= new ServiceHost(typeof(abImp));
var binding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(A), binding, aConnectionString);
host.AddServiceEndpoint(typeof(B), binding, bConnectionString);
{
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
aConnectionString
);
}
host.Open();
I'm getting this error message on the host.Open() operation:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: A binding instance has already been associated to listen URI 'http://localhost:8200/A'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.
SOLUTION
var aConnectionString = "http://localhost:" + portA+ "/A";
var bConnectionString = "http://localhost:" + portB+ "/B";
ServiceHost aHost = new ServiceHost(instance, new Uri(aConnectionString));
ServiceHost bHost = new ServiceHost(instance, new Uri(bConnectionString));
aHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
bHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
aHost.AddServiceEndpoint(typeof(A), new BasicHttpBinding(), aConnectionString);
bHost.AddServiceEndpoint(typeof(B), new BasicHttpBinding(), bConnectionString);
{
// Check to see if the service host already has a ServiceMetadataBehavior
var smb = aHost.Description.Behaviors.Find<ServiceMetadataBehavior>() ?? new ServiceMetadataBehavior();
aHost.Description.Behaviors.Add(smb);
aHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
aConnectionString + "/Mex"
);
}
{
// Check to see if the service host already has a ServiceMetadataBehavior
var smb = bHost.Description.Behaviors.Find<ServiceMetadataBehavior>() ?? new ServiceMetadataBehavior();
bHost.Description.Behaviors.Add(smb);
bHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
bConnectionString + "/Mex"
);
}
aHost.Open();
bHost.Open();
Given that you want two completely different addresses, only same implementation class, I'd recommend use of two different ServiceHost instances.
I have a question regarding the usage of 'AddServiceEndpoint' method of the 'ServiceHost' class.
It seems that adding a value to the 'address' parameter part of this method does not work.
Please refer to the code excerpt below:
Uri httpUrl = new Uri("http://localhost:8090/DuplexServer/SimpleCalculator");
host.AddServiceEndpoint(typeof(DuplexServer.ICalculatorDuplex), new WSDualHttpBinding(), "");
Here, in order to test, I can access this URL through a Web Browser:
http://localhost:8090/DuplexServer/SimpleCalculator and a webpage successfully shows.
However, if I implemented it this way instead:
Uri httpUrl = new Uri("http://localhost:8090/DuplexServer/");
host.AddServiceEndpoint(typeof(DuplexServer.ICalculatorDuplex), new WSDualHttpBinding(), "SimpleCalculator");
When I access : http://localhost:8090/DuplexServer/SimpleCalculator, a blank page appears.
The method is being run in the host project's file, which is a console app.
Whole code as requested:
class Program
{
static void Main(string[] args)
{
//Create a URI to serve as the base address
Uri httpUrl = new Uri("http://localhost:8090/DuplexServer/SimpleCalculator");
//Create ServiceHost
ServiceHost host = new ServiceHost(typeof(DuplexServer.CalculatorService), httpUrl);
//Add a service endpoint
host.AddServiceEndpoint(typeof(DuplexServer.ICalculatorDuplex), new WSDualHttpBinding(), "");
//Enable metadata exchange
/*
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
*/
//Start the Service
host.Open();
Console.WriteLine("Service is host at " + DateTime.Now.ToString());
Console.WriteLine("Host is running... Press <Enter> key to stop");
Console.ReadLine();
}
}
I would like to know the proper way to use the 'Address' parameter of this method.
Thanks.
I am writing WCF Service - Client. The service is getting the endpoint url as arg, This is Windows Form Application.
The Service impl is:
BaseAddress = new Uri(args[0]);
using (ServiceHost host = new ServiceHost(typeof(DriverService), BaseAddress))
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
//host.AddServiceEndpoint(typeof(DriverService), new BasicHttpBinding(), BaseAddress);
host.Open();
After host.Open() i get the error, When i wrote same wcf code on another solution it worked just fine, i had the client and service. now i just need to open the service when wait until the client connects.
From what I understand, this is Service and i give it address, then it listens on the given address and exposing the methods on the interface to different clients.
Error:
Service 'DriverHost.DriverService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
Code of interface and class:
[ServiceContract]
public interface IDriverService
{
[OperationContract]
string WhoAmI();
}
public class DriverService : IDriverService
{
public string WhoAmI()
{
return string.Format("Im on port !");
}
}
since there is different between .net 4.5 and 3.5 i understand there is no default Endpoints.
So needed to declare:
BaseAddress = new Uri(args[0]);
using (ServiceHost host = new ServiceHost(typeof(Namespace.Classname), BaseAddress))
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.AddServiceEndpoint(typeof(Namespace.IInterface), new BasicHttpBinding(), args[0]);
host.Open();
Meaning - add the .AddServiceEndpoint(..)
and make sure that on ServiceHost() write the class, and on AddServiceEndpoint enter the Interface.
I got a service which offers a named pipe as connection point/endpoint address for 3rd party applications.
what i did so far is:
Uri[] baseAddress = new Uri[]{
new Uri("net.pipe://localhost")};
string PipeName = "Calculator";
serviceHost = new ServiceHost(typeof(CalculatorImplementation), baseAddress);
// Add a mex endpoint
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.HttpGetUrl = new Uri("http://localhost:8001/CalculatorServer");
serviceHost.Description.Behaviors.Add(smb);
serviceHost.AddServiceEndpoint(typeof(ICalculator), new NetNamedPipeBinding(), PipeName);
serviceHost.Open();
I'm connecting in my client using a ChannelFactory like this:
ChannelFactory<ICalculator> pipeFactory = new ChannelFactory<ICalculator>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Calculator"));
ICalculator pipeProxy = pipeFactory.CreateChannel();
But acutally I wonder if there is a more "usual" way to connect to the service.
Does I really need to tell every 3rd party app the "connection string"/Endpoint Address of my named pipe ("net.pipe://localhost/Calculator") ?
I thought that there might be a better way to accomplish this, but I did not found a way to do this so far.
I created already that "mex endpoint" but I'm not sure how to use this endpoint to populate the named pipe.
My questions are:
I'm populating the service interface the right way?
and
How do I use the Metadata Endpoint in a client application right?