How to update client endpoint binding in code - c#

I have a question about modifying client endpoint binding in code.
I have added a web service reference and created a client endpoint binding for it.
In web.config I a binding set to basic https, which I want to change it to ex. http, which I have specified in web.config under the name "basicHttpBinding". When I create the instance of the web service reference, there is no way of using address and binding as there is not constructor that takes such arguments.
<endpoint address="http://localhost/LocalService/SendRequest.asmx"
binding="basicHttpsBinding" bindingConfiguration="basicHttpsBinding"
contract="LocalService.SendRequest" name="LocalServiceClient" />
Any advice how to solve this problem would be appreciated.
Cheers!

var binding = new System.ServiceModel.BasicHttpBinding() { Name = "LocalServiceClient", Namespace = "LocalService.SendRequest" };
var endPoint = new System.ServiceModel.EndpointAddress("http://localhost/LocalService/SendRequest.asmx");
var client = new ServiceClient(binding, endPoint);

If I understood correctly, this is what you are looking for:
var x = new ServiceClient();
x.Endpoint.Binding = new BasicHttpBinding("optional configuration name");

Related

How can I change the URL of my WCF Service?

I have this WCF Service:
http://localhost:56471/WcfPruebaService.svc
And I need it to be:
http://localhost:56471/ServiciosDePrueba/WcfPruebaService.svc
You just need to open app.config and replace the old address with the new one. Or if you want to change it in code (programmatically) you can use the following code:
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("***"));
MyServiceClient client = new MyServiceClient(binding, endpoint);
https://learn.microsoft.com/en-us/dotnet/framework/wcf/how-to-implement-a-wcf-contract#edit-appconfig
How to programmatically modify WCF app.config endpoint address setting?

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.

WCF service call from class project with proxy

I need to make a WCF service call to an external 3rd party using 2-way SSL from a class project. I have added the WSDL provided by the 3rd party to my project as a Service Reference. The problem is that all calls outside our domain (*.abc.com) pass through a proxy server
http://ironport:8080
This is what I have done in my code -
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.BypassProxyOnLocal = false;
binding.UseDefaultWebProxy = true;
binding.AllowCookies = false;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
var endpoint = new EndpointAddress("https://blablabla.com/GetData.svc");
var client = new AccountClient(binding, endpoint);
X509Certificate2 certi = new X509Certificate2(#"path to pfx file", "password");
client.ClientCredentials.ClientCertificate.Certificate = certi;
I make the service call using -
var account = client.ExportAccounts(obj1, obj2, obj3);
It then gives me an error -
The remote server returned an Error (407): Proxy authentication required
That is but obvious because nowhere did I mention the proxy details the request needs to go through. What I need is a way to add the following info from a web.config file of a different project into my request above -
<system.net>
<defaultProxy useDefaultCredentials="true">
<proxy proxyaddress="http://ironport:8080" />
<bypasslist>
<add address="[\w]+\.abc\.com$" />
</bypasslist>
</defaultProxy>
</system.net>
Is there some way to achieve this in code? Or do I need to go about this in a different way altogether? Let me know if I need to post more information.
You could try using the WebProxy Class. Not tested, but something like this:
WebProxy proxy = new WebProxy("http://ironport:8080");
proxy.BypassList = new string[] { "[\w]+\.abc\.com$" };
Another alternative would be to move the relevant section of the config to the web/app.config of the application that is using your class library.
ADDED
Not 100% sure this will work, but you could try adding this line to your code:
WebRequest.DefaultProxy = proxy;
Taken from this answer
Another option might be to use the ProxyAddress property of WsHttpBinding (make sure in that case you set the UseDefaultProxy to false), but I don't see a way to add a bypass list with this one.

Locally Hosted WCF service - I don't want clients to have to authenticate

I have a self-hosted WCF service that is hosted by a desktop application.
I can successfully connect to the service locally on my PC, but I can't use the service remotely, at least without providing my windows/domain level credentials.
I use the following code to start the service in the app:
ServiceHost host = new ServiceHost(
typeof (SMService),
new Uri("net.tcp://localhost:" + SMGlobals._DEFAULTSERVICEPORT.ToString() + "/SMService"));
host.AddServiceEndpoint(
typeof(ISMService),
new NetTcpBinding(),
"");
System.ServiceModel.Channels.Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
var metadataBehavior =
new ServiceMetadataBehavior();
host.Description.Behaviors.Add(metadataBehavior);
host.AddServiceEndpoint(
typeof(IMetadataExchange),
mexBinding,
"net.tcp://localhost:" + SMGlobals._DEFAULTSERVICEPORT.ToString() + "/SMService/mex");
host.Open();
SMGlobals.SMServiceHost = host;
If I create a simple client to call the service using the following code:
var client = new SMServiceClient();
var uri = "net.tcp://192.168.11.10:8760/SMService";
client.Endpoint.Address = new EndpointAddress(uri);
var initiateResponse = client.InitiateAuthentication(new InitiateAuthenticationRequest());
MessageBox.Show("Success!");
I receive the following exception:
System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed
Now, from other research, I have discovered that I could provide my credentials with the client call using the following code:
var client = new SMServiceClient();
var uri = "net.tcp://192.168.11.10:8760/SMService";
client.Endpoint.Address = new EndpointAddress(uri);
client.ClientCredentials.Windows.ClientCredential.Domain = "domain";
client.ClientCredentials.Windows.ClientCredential.UserName = "my_user_name";
client.ClientCredentials.Windows.ClientCredential.Password = "my_password";
var initiateResponse = client.InitiateAuthentication(new InitiateAuthenticationRequest());
MessageBox.Show("Success!");
And now, the code successfully completes.
I'm having a hard time figuring out how to remove this requirement. I've tried messing around with the binding setup on the client without success.
Can anyone point me in the right direction?
A Tcp Binding has security enabled by default, so to get what you want, you need to explicitly turn it off. Add your endpoint like this. You might also explore the MSDN help for NetTcpBinding as you might want to user an alternate constructor to also switch off reliable messaging.
host.AddServiceEndpoint(
typeof(ISMService),
new NetTcpBinding(SecurityMode.None),
"");
Set the appropriate Authentication on the Binding.
ClientAuthenticationType="None"
I had a similar issue. Worked locally between two processes but the same code failed when the two processes were put on different machines (or locally using a public URL that resolved to the local machine, e.g. mylocalmachine.corp.com). I found that I needed to explicitly set the Anonymous binding's security to 'None':
<binding name="TcpAnonymousBinding" portSharingEnabled="true" receiveTimeout="24:00:00">
<security mode="None"/>
</binding>

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

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);
}

Categories

Resources