Using a C# Service Reference SOAP Client with different Endpoint URIs - c#

I have a SOAP Webservice that is available on multiple servers, thus having multiple endpoints. I want to avoid adding multiple Service References (C# SOAP Port Clients) with different names just to talk to this services, since the API is exactly the same.
Is there a way to configure the Endpoint URI at runtime?

I use the following which works great:
ServiceReference1.wsSoapClient ws= new ServiceReference1.wsSoapClient();
ws.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://xxx/myservice.asmx");

I had trouble finding this one also. I finally just borrowed the configuration binding and did this:
private static wsXXXX.IwsXXXXClient wsXXXXClientByServer(string sServer)
{
// strangely, these two are equivalent
WSHttpBinding binding = new WSHttpBinding("WSHttpBinding_IwsXXXX");
// WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message, false);
EndpointAddress remoteAddress = new EndpointAddress(new Uri(string.Format("http://{0}:8732/wsXXXX/", sServer)), new UpnEndpointIdentity("PagingService#rl.gov"));
return new wsXXXX.IwsXXXXClient(binding, remoteAddress);
}

Related

Support HTTP and HTTPS in a SOAP service reference

I imported a SOAP service by using "Add -> Service reference" in Visual Studio. This generates a lot code that helps for consuming the service.
The SOAP has to call different endpoints for every different customer base using the application. Some are endpoints are in plain HTTP, and others are HTTPS. (All on internal network so HTTP is not a big deal). Every HTTP endpoint works fine, every HTTPS endpoint works, but the application wont support both.
This configuration supports HTTPS:
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.ServiceV201209Soap))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.Security.Mode = BasicHttpSecurityMode.Transport;
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
Removing the "Security.Mode" line will support HTTP.
I have trouble switching between the modes. The best that I could do was check wether the end point was HTTP or HTTPS, and change the binding configuration during runtime. But this made it work only on the second SOAP call after switching endpoints. That is horrible so I scrapped that.
Is there a simple configuration that definitely supports both?

Multiple contracts in one service can not be discovered on Client using WCF Discovery

I want to develop a WCF service to support multiple contracts. I managed to make this work by following the instruction from this post on Stackoverflow.
So basically create one service(FooBarService) to implement multiple contracts(IFooService, IBarService).
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
ServiceHost selfServiceHost = new ServiceHost(typeof(FooBarService));
// The endpoints need to share this binding.
var binding = new NetTcpBinding();
selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);
But the challenging thing is that I want to also make this service discoverable using WCF Discovery in order to decouple client and service from endpoint binding.
In the Service side, I did something like this:
var discoveryBehavior = new ServiceDiscoveryBehavior();
discoveryBehavior.AnnouncementEndpoints.Add(new AnnouncementEndpoint(new NetTcpBinding(SecurityMode.None), new EndpointAddress("net.tcp://localhost:8001/Announcement")));
_serviceHost.Description.Behaviors.Add(discoveryBehavior);
_serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
It seems that the service can work.
But on one of client that want to only use contract IFooService, I always got the following error when I try to discover it.
Unable to discover the endpoint for contract.IFooService. Either no service exists or it does not support discovery.
Do you think if it is possible to achieve discoverable multiple contracts in one service in this case?
If YES, how can I do that based on the code i have right now?.
Thanks.
I would think it would be possible. Try doing the simplest thing first to see if that works:
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
ServiceHost selfServiceHost = new ServiceHost(typeof(FooBarService));
// The endpoints need to share this binding.
var binding = new NetTcpBinding();
selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);
// Add ServiceDiscoveryBehavior
selfServiceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// Add a UdpDiscoveryEndpoint
selfServiceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Client:
static EndpointAddress FindCalculatorServiceAddress()
{
// Create DiscoveryClient
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
// Find ICalculatorService endpoints
FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(IFooService)));
if (findResponse.Endpoints.Count > 0)
{
return findResponse.Endpoints[0].Address;
}
else
{
return null;
}
}
Also make sure that you can create clients with the two different contracts and call the services manually.

How to call wcf service with out added service reference using channel factory

Can any one help me on this.
"How to call wcf service with out added service reference using channel factory".
I have used this code :
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("");
ChannelFactory factory = new ChannelFactory<IUnityServiceChannel>(binding, address);
UnityServiceClient channel = new UnityServiceClient();
string token = channel.GetSecurityToken(svcUsername, svcPassword);
But I want to create the IUnityServiceChannel run time. I don't have any information about the IUnityServiceChannel.
So can you help me how to crate interface using reflection or some thing else.

Different services on different ports in WCF

I'm in a situation where I want to use WCF to expose two different interfaces:
Internal (IPC communication)
External (Http REST)
The external interface shouldn't be able to see or use the internal interface so what I was thinking about were to host the two services on different ports e.g. (8000 for internal and 8001 for external) and then block all external communication on port 8000.
Moreover, I tried fiddling around with using named pipes for IPC communication, and I ran into an issue. If the unexpected situation occurs, that the service crashes or goes offline the client would also have to be restarted to be able to establish the communication with the service via the named pipes. Is this normal behavior and can it be avoided?
I have the following code so far:
// Service Host
var host = new ServiceHost(serviceContract, new Uri(_address));
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
var behaviour = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
// Local Endpoint
host.AddServiceEndpoint(typeof(ILocalServiceContract), new BasicHttpBinding(), "Local");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
// External Endpoint
var webHttpBidning = new WebHttpBinding { TransferMode = TransferMode.Streamed };
var externalEndPoint = host.AddServiceEndpoint(typeof(IExternalServiceContract), webHttpBidning, "External");
externalEndPoint.Behaviors.Add(new WebHttpBehavior());
They are currently both hosted on the same port which I want to avoid, I'm fairly new to WCF and I could really use some guidance for best practice and what I'm doing wrong. As mentioned earlier the 'BasicHttpBinding' could maybe be replaced with a named pipe if my issue can be resolved.
Looking forward to hear to the experts and if you need any clearification feel free to ask :)
I solved the issue with the following code on server. On the clients which communicate with the server via named pipes, I used "WcfClientProxyGenerator" library to generate fault tolerant client proxies.
_namedPipeAddress = "net.pipe://localhost/";
_httpAddress = "http://localhost:8000";
var host = new ServiceHost(serviceContract, new Uri(_namedPipeAddress), new Uri(_httpAddress));
host.Description.Behaviors.Add(new ServiceMetadataBehavior { });
var behaviour = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
behaviour.IncludeExceptionDetailInFaults = true;
// Local Endpoint
host.AddServiceEndpoint(typeof(ILocalServiceContract), new NetNamedPipeBinding(), "Local");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexNamedPipeBinding(), "mex");
//// External Endpoint
var webHttpBidning = new WebHttpBinding { TransferMode = TransferMode.Streamed };
var externalEndPoint = host.AddServiceEndpoint(typeof(IExternalServiceContract), webHttpBidning, new Uri(_httpAddress));
externalEndPoint.Behaviors.Add(new WebHttpBehavior());
For further improvements to this solution feel free to comment :)

WCF - Create client programmatically only from endpoint name

My WCF client can connect to several endpoints. But they all have different addresses, bindings and contracts. So my question is : How can I create my WCF client programmatically depending just of the name of my endpoint I want to connect to (which I have in my code)
If I understood your question correctly, I believe this is the answer [using IPC, can be easily converted to other communication types]
Listener:
_host = new ServiceHost(typeof(ContractClass));
_host.AddServiceEndpoint(typeof(IContract), new NetNamedPipeBinding(), new Uri("net.pipe://localhost/" + listenerEndpointName));
_host.Open();
Client:
var factory = new ChannelFactory<IContract>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/" + listenerEndpointName));
IContract proxy = factory.CreateChannel();

Categories

Resources