Calling a WCF service from another WCF service - wcf

I have a WCF service hosted on a windows service on my Server1. It also has IIS on this machine. I call the service from a web app and it works fine. But within this service, I have to call another WCF sevice (also hosted on a windows service) located on Server2. The security credentials are set to "Message" and "Username". I have an error like "SOAP protcol negociation failed". It's a problem with my server certificate public key that doesn't seem to be recognise. However, if I call the service on the Server2 from Server1 in a console app, it works fine.
I followed this tutorial to set up my certificates : http://www.codeproject.com/KB/WCF/wcf_certificates.aspx
Here's the config file from my service on Server1 that tries to call the second one :
<endpoint address=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.ITraitement" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<client>
<endpoint address="http://Server2:8000/servicemodelsamples/service"
behaviorConfiguration="myClientBehavior" binding="wsHttpBinding"
bindingConfiguration="MybindingCon" contract="Microsoft.ServiceModel.Samples.ICalculator"
name="">
<identity>
<dns value="ODWCertificatServeur" />
</identity>
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="MybindingCon">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceTraitementBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="myClientBehavior">
<clientCredentials>
<clientCertificate findValue="MachineServiceTraitement" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
<serviceCertificate>
<authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
And here's the config file from the web app that calls the service on Server1 :
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ITraitement" 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://localhost:8020/ServiceTraitementPC"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITraitement"
contract="ITraitement" name="WSHttpBinding_ITraitement">
</endpoint>
</client>
Any idea why it works if if I call it in a console app and not from my service ? Maybe it has something to do with the certificateValidationMode="ChainTrust" ?

Well, finally it was just a matter of trusting the issuer of the certificate on the client machine. It was mentioned in the tutorial and I must have missed that step. Still wonder why it worked when calling from a console app, but... anyway, it works fine now.
Thanks !

When you call the service from the console app you are in the security context of the logged in user.
When you call the service from a service running in IIS, with default settings, you are in the security context of a local account NETWORK SERVICE.
The way to fix it is probably to set impersonate=true in the system.web section of your web.config.

Related

WCF Callback Service with netTcp Binding timeout after 10 mins

I'm creating a chat application with WCF(using callback contract) and netTcpBinding.
I'm hosting the service as a windows service and accessing it from other computers
via the client application.
The problem that i'm facing now is the clients connection comes to a Fault state after
10 mins which seems to be some kind of timeout that occur.
I already tried increasing the received timeout and send timeout in both service and client but didn't work.
which setting should i change to increase this timeout period and in which application, service or client?
Following are my configuration files,
Service
<system.serviceModel>
<services>
<service behaviorConfiguration="PeerTalk.Service.ChatServiceBehavior"
name="PeerTalk.Service.ChatService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration=""
contract="PeerTalk.Service.ServiceContracts.IChat">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:7920/ChatService" />
<add baseAddress="net.tcp://localhost:7921/ChatService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="PeerTalk.Service.ChatServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpBinding"
maxBufferSize="67108864"
maxReceivedMessageSize="67108864"
maxBufferPoolSize="67108864"
transferMode="Buffered"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:00:10"
sendTimeout="00:00:10"
maxConnections="100">
<readerQuotas maxDepth="64"
maxStringContentLength="67108864"
maxArrayLength="67108864"
maxBytesPerRead="67108864"
maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows"/>
</security>
<reliableSession enabled="false" inactivityTimeout="00:01:00"/>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Client
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IChat" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:00:10" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="67108864"
maxBufferSize="67108864" maxConnections="10" maxReceivedMessageSize="67108864">
<readerQuotas maxDepth="32" maxStringContentLength="67108864"
maxArrayLength="67108864" maxBytesPerRead="67108864" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:01:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://10.10.10.45:7921/ChatService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IChat" contract="PeerTalkService.IChat"
name="NetTcpBinding_IChat">
</endpoint>
</client>
</system.serviceModel>
Thanks.
The timeout in this case is defined by both receiveTimeout in the binding and inactivityTimeout in reliable session which is used for duplex messaging. The correct solution is not increasing timeout but implementing some ping / keep alive messages. The reason is that increasing timeout will keep connections open for failed clients.
Can you post client call sample (service call example). What might happening here is that you are not closing client correctly and you reach maximum sessions on service side.
You must be aware that using net.tcp binding is different than http.
You can use System.ServiceModel performance counters (http://msdn.microsoft.com/en-us/library/ms750527.aspx) and see after 10 minutes what is happening (number of calls outstanding, number of service instances, etc..)
http://dkochnev.blogspot.com/2011/06/wcf-framework-40-monitoring-service.html

WCF: The request for security token could not be satisfied because authentication failed

I'm working on an WCF service that is secured by Oauth via DotnetOpenAuth.
Somewhere I've got a configuration error that's causing the error "The request for security token could not be satisfied because authentication failed." in my code and I can't see to find a setup that works.
Works fine localhost to localhost but once I put it on my server (not on the domain) it fails from that server to itself or from localhost to the server.
I'm a little worried about some of the other solutions on this site as they seem to disable security. Mostly it's that they don't seem to work for me.
Provider:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="DataApiBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization serviceAuthorizationManagerType="OAuthServiceProvider.Code.OAuthAuthorizationManager, OAuthServiceProvider" principalPermissionMode="Custom" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="DataApiBehavior" name="OAuthServiceProvider.DataApi">
<endpoint address="" binding="wsHttpBinding" contract="OAuthServiceProvider.Code.IDataApi">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://devel.nanaimo.ca/" />
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
Consumer:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IDataApi" 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" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://devel.nanaimo.ca/NanaimoProfile/DataApi.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDataApi"
contract="CodeServiceOauthProvider.IDataApi" name="WSHttpBinding_IDataApi">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Update: Looks like OAuthServiceProvider.Code.OAuthAuthorizationManager Is not being called on live. It's instantiated but CheckAccessCore is never called. I have no idea why yet.
This is just blind shot but AuthorizationManager is used to authorize users and it is called after authentication but you have your service configured with default WsHttpBinding - it uses message security with Windows authentication. Windows authentication doesn't work between computers which are not part of the same domain.
I would start with basicHttpBinding which defaults to no security (no authentication). If it works then you can think about what security do you expect.
I eventually just created a windows username and password with very little rights and hard coded the username into my library. Certificated could have been another answer but I never got them to work.

WCF - "There was no endpoint listening at..." error

I have two applications that I want to test locally on the same machine. App 1 has a simple WCF service with the folloiwng config entry:
<service behaviorConfiguration="MyNamespace.ContainerManagementServiceBehavior"
name="MyNamespace.ContainerManagementService">
<endpoint address="ContainerManagementService" binding="basicHttpBinding"
name="ContainerManagementbasicHttpEndpoint"
contract="MyNamespace.IContainer" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ContainerManagementService" />
</baseAddresses>
</host>
</service>
<behaviors>
<behavior name="MyNamespace.ContainerManagementServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</behaviors>
I start the service by running the web application project where it is hosted. I am able to successfully browse to the url and get web service information page from ie. I copy the same URL and use it for my client.
My other client, App 2, has the following in its config file:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttp" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00"
sendTimeout="00:10:00" allowCookies="false"
bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="5242880" maxBufferPoolSize="524288"
maxReceivedMessageSize="5242880" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="5242880" />
<security mode="None">
<transport clientCredentialType="None"
proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:3227/Services/ContainerManagementService.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttp"
contract="MyService.IService" name="externalService" />
</client>
</system.serviceModel>
However, when I try to execute a WCF call form client to the running service, I get the following error message:
There was no endpoint listening at
http://localhost:3227/Services/ContainerManagementService.svc
that could accept the message. This is often caused by an incorrect
address or SOAP action. See InnerException, if present, for more details.
What could be happening?
It looks likes the issue is due to the fact that both server and client are being run from the Cassini server. I am changing the architecture to host the server endpoint in IIS.
Do you have two applications ?
One which hosts the server endpoint and the other which is the client ? Are both active in IIS (considering the second application is a web app) ?
If you have two projects for those two components in your solution, you can configure VS to start both project at the same time. This way you can put breakpoints on both the client and the server and see if the server really gets called by the client or if the exception happens without the server method being called.
If your web service is on: http://localhost:8000/ContainerManagementService.svc
Your client app2 should point on this same addres:
<client>
<endpoint address="http://localhost:8000/ContainerManagementService.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttp"
contract="MyService.IService" name="externalService" />
</client>

WCF IIS-hosted wsHttpBinding service - svcutil generates proxy with basicHttpBinding!

I consider myself pretty expert at WCF but this has me stumped. I don't know if this is a .NET Framework 4/WCF 4 thing with it's automatic configuration or what but I am getting strange behavior. I basically have a WCF 4 WCF service hosted in IIS project. It all worked and then I went in and switched the config from basicHttpBinding to wsHttpBinding. I tried to Update the Service Reference in my consuming app and I get basicHttpBinding output in the generated config. So, of course, I dropped down and ran svcutil.exe aggainst the .svc file and same results. This is the config file (Blah substituted for name that I can't use in public):
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows"></authentication>
<identity impersonate="true"/>
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpEndpointBinding">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="Blah.Services.RONScheduler.BlahService.BlahDataServiceBehavior"
name="Blah.Services.RONScheduler.FAMService">
<endpoint address="BlahDataService" binding="wsHttpBinding" bindingConfiguration="WSHttpEndpointBinding"
name="WSHttpEndpoint" contract="Blah.Services.RONScheduler.FAMService.IBlahDataService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Blah.Services.RONScheduler.BlahService.BlahDataServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
This is what I get generated out before I clean out the unncessary stuff:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IBlahDataService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/BlahService/BlahDataService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IBlahDataService"
contract="IBlahDataService" name="BasicHttpBinding_IBlahDataService" />
</client>
</system.serviceModel>
As you can see it's as if it's ignoring the wsHttpBinding setting in the config. What gives?
Have you checked your default protocol bindings, a new feature in WCF 4 ??
By default, they're in your machine.config, and should look like this:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="" />
<add scheme="net.tcp" binding="netTcpBinding" bindingConfiguration=""/>
<add scheme="net.pipe" binding="netNamedPipeBinding" bindingConfiguration=""/>
<add scheme="net.msmq" binding="netMsmqBinding" bindingConfiguration=""/>
</protocolMapping>
So this kinda implies to me that if you're hitting a HTTP address, WCF 4 will use basicHttpBinding by default.
You can change those bindings in your own configs, if needed.
Found this in A Developer's Introduction to Windows Communication Foundation 4
Given the configurations you provided, my guess would be that the service name is invalid and the host falls back to default configuration.
Make sure the service name matches the implementation class name.
I came to this conclusion because the interface name is Blah.Services.RONScheduler.FAMService.IBlahDataService and the class name is Blah.Services.RONScheduler.FAMService. It looks like there is something missing after FAMService.

File upload using WCF service not working when transferMode="Streamed"

Configuration details are as follows:
Web.config of Wcf service which is hosted.
<basicHttpBinding>
<binding name="HttpBinding_MTOM" messageEncoding="Mtom"
transferMode="Streamed" maxBufferSize="65536"
maxReceivedMessageSize="534773760">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
<services>
<service name="OA.Smart.Services.FileTransferService"
behaviorConfiguration="FileTransferServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="HttpBinding_MTOM"
contract="OA.Smart.ServiceContract.IFileTransferService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behavior name="FileTransferServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
I have a smart client application which accesses this WCF service.App.Config is as follows
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFileTransferService"
closeTimeout="00:30:00" openTimeout="00:30:
receiveTimeout="00:30:00" sendTimeout="00:30:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Mtom" textEncoding="utf-8"
transferMode="Streamed" useDefaultWebProxy="true">
<readerQuotas
maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:4149/OA.Smart.ServiceHost/FileTransferService.svc"
behaviorConfiguration="defaultServiceBehaviour"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IFileTransferService"
contract="FileTransferServiceReference.IFileTransferService"
name="BasicHttpBinding_IFileTransferService">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="defaultServiceBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
With this configuration in place whenever i try to upload my file,It throws as error
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.
HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)}
However if i change transferMode="Streamed" to "Buffered" it works as expected. I do not understand why it behaves this way. TransferMode of WCF service is streamed, so it should work with streamed.
Please tell me how to make it work with transferMode="Streamed"
Problem was with hosting WCF services.I had hosted them on Cassini(Web server which ships with VS2008) instead of IIS.Cassini does not allow streaming over HTTP.So just using IIS to host WCF services resolved this issue.
You only want to upload files to the server? In that case, have you tried using
transferMode="StreamedRequest"
instead of "Streamed" ?? Any difference?
Also, can you show us the service contract (the interface you're programming against) ?? That might also gives us a clue.
Marc