Im consuming some webservice from a third-party product.
So ive add righ-clicking on service reference and generating the code on the web.config file.
But the problem is, foreach company i consume the service, they have one endpoint address (and they have more then 30 companies). So, its insane to add one reference foreach company (to execute the same method in these webservices).
So, i would like to know if it is possible and how can i do a WebServiceHelper class, with some GetWebService(url) method wich allows me send just the url of the webservice and create my service model.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ITestService" receiveTimeout="10:00:00"
sendTimeout="10:00:00" maxReceivedMessageSize="2147483647" transferMode="Buffered"
useDefaultWebProxy="true" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xxxx.xxx"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITestService"
contract="Test.TESTSOAP" name="BasicHttpBinding_ITestService" />
</client>
We should be able to create a c# file from WSDL, same way as SVCUTIL does and then use reflection to create a proxy at run time.
Please follow through this article and download the source code provided.
DynamicProxyFactory
Related
we have developed a WCF webservice and it has been working fine without any requirement of SSL being introduced. Now, before deploying it to Test envirnment we need to make it SSL enabled.
So I came across this link on SO : Enable SSL for my WCF service
and changed my config file to include following code:
<binding name="BasicHttpBinding_IPromotionalSponsorship" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
<security mode="Transport">
</security>
</binding>
While my endpoint looks like following
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPromotionalSponsorship"
name="StandardEndpoint" contract="PL.Commercial.PromoSponsor.Service.Contracts.IPromotionalSponsorship" />
But it does not sound like it changed anything still when I run my project, it shows the URL without https.
Now, when i explicitly add 's' in the URl it throws following error:
Unable to make a secure connection to the server. This may be a
problem with the server, or it may be requiring a client
authentication certificate that you don't have.
I have created a self-signed certificate and added it to my local IIS. Anything special that I need to change/add?
You need to do following changes.
If you don't need client authentication and just HTTPS then your binding configuration should look like below. Note transport element.
<binding name="BasicHttpBinding_IPromotionalSponsorship" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
If you want browser to display https when you browse service. Your service behaviour should look like below.
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="True" httpsGetBinding="mexHttpsBinding"/>
</behavior>
</serviceBehaviors>
</behaviors>
If you are getting error "Unable to make a secure connection to the server..." as mentioned in question that means you have configured service in such way that it requires client certificate. I guess you just need to enable HTTPS. In that case you don't need to configure client certificate requirement in IIS.
Your application's SSL settings should look like this.
I am pretty new to WCF and I was hoping someone could point me in the right direction.
Basically, I am trying to pull information from an existing WCF which was not developed by me.
So, for testing purposes, I created a console application and added the svc as a service reference.
I create a new instance of the client, and whenever I try to execute any of the methods, I get the following error:
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
Does this mean the WCF requires a signed certificate to authenticate the client?
If this is the case, do I need to request/provide anything from/to the WCF's provider?
I´ve looked through several post related to this issue, but all these scenarios are based on the assumption that you have access to the server.
EDIT
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="..." />
<binding name="SecureByTransport">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/Web/ConnectWcf.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ConnectBasic"
contract="ConnectBasic.IConnectBasic" name="BasicHttpBinding_IConnectBasic" />
<endpoint address="https://localhost/Web/ConnectBasicWcf.svc"
binding="basicHttpBinding" bindingConfiguration="SecureByTransport"
contract="ConnectBasic.IConnectBasic" name="SecureByTransport" />
</client>
</system.serviceModel>
</configuration>
I have to connect to a legacy web service.
In visual studio, if I do a Add Service Reference, then enter the url of the WSDL file on server. My service shows up, and I write the code against it. But when I run the code I get this error:
System.ServiceModel.CommunicationException: The envelope version of
the incoming message (Soap12
(http://www.w3.org/2003/05/soap-envelope)) does not match that of the
encoder (Soap11 (http://schemas.xmlsoap.org/soap/envelope/)). Make
sure the binding is configured with the same version as the expected
messages.
My app.config looks like this:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="LoginServiceSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://server/Service.asmx" binding="basicHttpBinding"
bindingConfiguration="LoginServiceSoap" contract="Stuff.Login.LoginServiceSoap"
name="LoginServiceSoap" />
</client>
</system.serviceModel>
However, I am able to communicate with the service fine, if I add a 'Web Reference'. But my understanding is that I am supposed to use Service References now, instead of WebReferences. I am assuming I have something wrong in my above config.
Or am I forced to use a Web Reference, because of the type of service I am connecting to?
Sheamus,
You could (theoretically) add the version number to the binding definition.
envelopeVersion="None/Soap11/Soap12"
With, of course, the right value for your service.
So it would look more like:
<basicHttpBinding>
<binding name="LoginServiceSoap"
envelopeVersion="Soap12" />
</basicHttpBinding>
Hope this helps you do things your way.
I'm a noob; please help me understand this authentication config / bindings stuff that confuses me so much.
I have a C# WCF service deployed on IIS 7 on Win 2008. My client is a Windows Forms C# app. My client works just fine when it's running from the same server where the WCF service is running, but when I try to run my client from a remote PC, I get the following exception...
System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service.
I've read a few posts about these issues, and know that my problem is because my service and client are configured to use Windows authentication, which I guess is the default when using Visual Studio to create the service, and to add the service reference to the client. Below is my config before I made any changes, when it was still set to Windows (with irrelevant bits removed)...
Web.Config
<system.web>
...
<authentication mode="Windows"/>
...
<system.serviceModel>
<services>
<service name="MCLaborServer.LaborService" behaviorConfiguration="MCLaborServer.LaborServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" contract="MCLaborServer.ILaborService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MCLaborServer.LaborServiceBehavior">
<!-- 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>
And from the App.Config on the client...
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ILaborService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://<myDnsNameGoesHere>/MCLaborServer/LaborService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ILaborService"
contract="LaborService.ILaborService" name="WSHttpBinding_ILaborService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
So, first I changed "authentication mode="None"" in the web.config, and set "security mode="None"" in the client's app.config, and set both the clientCredentialType="None" for message and transport. I also commented out the "identity" sections in both the web.config and client's app.config. That broke it completely though and now the client running locally won't even work; it gives a "The remote server returned an unexpected response: (405) Method Not Allowed" error.
So what can I do to turn security off so that I can connect using a remote client? I do have anonymous access enabled by the way in IIS for my application.
I'd also like to ask, what's the best practice way to configure this so I can make webservice calls on a remote client over the internet in a semi-secure fashion without using SSL or doing anything that would cost money. I'm not really that concerned about security of the data because it's not really sensitive data, but still I'd like to make sure the server isn't open to attacks.
Also, I read that I can use Windows authentication, and then explicitly specify credentials in code, like below. If I do that, will it still work remotely? And if so, does that end up making my Windows credentials for the server be sent over the wire in an insecure fashion, so then I'd be open to getting my credentials hijacked?
SomeService.ServiceClient someService = new SomeService.ServiceClient();
someService.ClientCredentials.Windows.ClientCredential.UserName="windowsuseraccountname"
someService.ClientCredentials.Windows.ClientCredential.Password="windowsuseraccountpassword"
I've read through the following posts / links, but still am confused. Thanks for any help!
WCF error: The caller was not authenticated by the service
How to fix "The caller was not authenticated by the service"?
http://msdn.microsoft.com/en-us/library/aa291347(v=vs.71).aspx
http://www.devx.com/codemag/Article/33342/1763/page/2
We ran into similar issues when setting up low security WCF services that ran across domains. One of the biggest problems (if you can call it that) is that WCF is configured to be very secure by default. Because our application was entirely within a secure network, we did not want to have to bother with a lot of complicated certificates. Our workaround was to create a custom binding that allowed us to use username/password authentication for our services without any encryption. We based our implementation off of Yaron Naveh's Clear Username Binding. I would recommend that you have a look at that (and at his blog post introducing it).
Some good resources for learning about WCF Bindings and Security:
MSDN - Windows Communication Foundation Bindings Overview
MSDN - System-Provided Bindings
MSDN - Security Overview
MSDN - Programming WCF Security
MSDN - WCF Security Fundamentals
MSDN - Choosing a Transport
I fixed this by changing binding to basicHttpBinding, changing authentication to Forms and turning security off.
We're using UsernamePasswordValidator along with a certificate to secure access to our WCF services.
However, the custom authorization policies we're using are SERVICE behaviors, not endpoint behaviors, so they apply to all endpoints, including the MEX endpoint. We'd like to be able to go and grab the service references using visual studio without having to comment out the service behaviors every time, but since both the mex and the wshttp endpoint are secured, we get an error when doing "Add Service Reference.."
Is there any way around this?
Are you using the same binding on both? If so, try 2 seperate bindings - one for the mex endpoint and one for the wshttp:
So for the service - something like:
<wsHttpBinding><binding name="wsHttpBindingMessageUname">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="true"
establishSecurityContext="false" />
</security></binding></wsHttpBinding>
and for the mex endpoint (no security):
<customBinding><binding name="customMex">
<textMessageEncoding>
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpTransport transferMode="Buffered"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"/></binding></customBinding>
Service endpoints will be something like:
<endpoint address="" behaviorConfiguration="Server.Services.DefaultEndpointBehavior" binding="wsHttpBinding" bindingConfiguration="wsHttpBindingMessageUname" name="DefaultHttp" contract="Server.Services.IMyService" listenUriMode="Explicit" />
<endpoint address="mex" binding="customBinding" contract="IMetadataExchange" name="" bindingConfiguration="customMex" listenUriMode="Explicit" />
With this setup, it's not applying the security for mex so you shouldn't get that message when trying to update service reference. Either that, or create another secure binding that uses different credentials, i.e. a client certificate on your machine.
The following MSDN post has a sample of this and more info can be found on this blog regarding secure mex endpoints.
I think from the question he also noted that he was using Service Behaviours, so the binding configuration wont make a difference, since the entire service uses the UserNamePassword Validator.
Two things come to mind here.
Remove the explicit mex binding and add under service behaviors
<serviceMetadata httpsGetEnabled="true" />
Or Keep the mex binding, and enable
<serviceMetadata httpGetEnabled="true" />
CustomUserNameValidator doesnt get executed when requesting Metadata,
so if httpsgetenabled isnt on, and you have a mex binding on http, you need
httpGetenabled on at least