I have a really strange problem with one of my WCF services. I'm pretty sure that most people who have experimented with WCF services have had an EndpointNotFoundException thrown when an endpoint had not been set up correctly in one of their configuration files. From the EndpointNotFoundException class page on MSDN:
The exception that is thrown when a remote endpoint could not be found or reached.
Further on, it continues:
The endpoint may not be found or reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
This does not reflect my situation. So it seems that receiving an EndpointNotFoundException when working with WCF is not unusual, but this Exception is not thrown when first trying to access the service... instead, it is thrown only when trying to call one of the operations of the service:
using (ExportConfirmationServiceClient client = new ExportConfirmationServiceClient(
"WebHttpBinding_IExportConfirmationService")) // <-- Exception is NOT thrown here
{
...
component releaseConfirmation = DeserializeTestXmlFile(filePath);
client.AddExportConfirmation("5051275066302", releaseConfirmation);
// Exception is thrown on call to service operation on line above
...
}
Interestingly, the Exception message also includes the name of the operation in the mentioned file path:
There was no endpoint listening at http://domain/Folder/ServiceName.svc/OperationName that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The inner Exception has the following message:
The remote server returned an error: (404) Not Found.
This is particularly confusing for me as I can successfully browse to the service URL and see the default You have created a service page:
Also, if I navigate to the path in the Exception message, I see an Endpoint not found message on the page:
However, if I navigate to any operation page of one of my other, working WCF services, I get a standard 400 Bad Request error from the browser, even though the operation works fine. So it would seem to me as if this original EndpointNotFoundException could be a red herring... I'm really not sure though, as I've not spent much time working with WCF.
I'll show my web.config (server side) here just in case anyone needs to see it:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
<services>
<service name="Midas.WebConfirmations.ExportConfirmationService" behaviorConfiguration="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<endpoint address="" binding="webHttpBinding" contract="Midas.WebConfirmations.IExportConfirmationService" behaviorConfiguration="webHttp" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is the client App.config (bear in mind that this references two WCF services):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDataService" 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>
<webHttpBinding>
<binding name="WebHttpBinding_IExportConfirmationService" allowCookies="true" maxReceivedMessageSize="20000000" maxBufferSize="20000000" maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32" maxArrayLength="200000000" maxStringContentLength="200000000"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Midas.WebConfirmations.ExportConfirmationServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webEndpointBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Xml" helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://devbucket.ministryofsound.mos.local/MidasWebServices/DataService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDataService" contract="Midas.WebServiceClients.IDataService" name="BasicHttpBinding_IDataService" />
<endpoint address="http://devbucket.ministryofsound.mos.local/MidasWebConfirmations/ExportConfirmationService.svc" binding="webHttpBinding" bindingConfiguration="WebHttpBinding_IExportConfirmationService" behaviorConfiguration="webEndpointBehavior" contract="IExportConfirmationService" name="WebHttpBinding_IExportConfirmationService" />
</client>
</system.serviceModel>
</configuration>
So if any of the great minds that frequent Stack Overflow could shed some light on this problem for me, I'd greatly appreciate it.
UPDATE >>>
In response to the first few comments, I suspected that the problem could be caused by an Exception being thrown from the server side code, so I simplified the operation code dramatically... now all it does is this, but I still get the same error:
public void AddExportConfirmation(string upc, component ingestionFeedback)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
}
Also, I did set up tracing, but it only worked on the client side, so it only told me what I already knew. I will have a look at the link you provided #BigDaddy, in case it shows how to set up tracing on the server side.
In response to Tewr, I generated the service client using svcutil.exe, but I also tried adding a service reference and letting Visual Studio create the reference for me... both methods resulted in the same error. Also, I have been updating the service references all day, as I've been making changes. The includeExceptionDetailInFaults="true" setting didn't make any difference, but I'll try adding a dummy operation to the service and try to view it in the browser.
UPDATE 2 >>>
Ok, so I added a simple getter method to the service and updated the references all round like #Tewr suggested. This has just made me more confused... the method:
[XmlSerializerFormat()]
[OperationContract]
[WebGet()]
string GetString();
The implementation just returns a string and I see that value when I access the service in a web browser:
However, I still get the same error from code, even when calling this same new operation... what does that mean?
UPDATE 3 >>>
After taking the advice from the comments, I set up a Service Trace on the service again... I still couldn't get the one working on the server, but on the client, it did output a trace file. In that file, I see an InvalidOperationException with the following message:
Envelope Version 'EnvelopeNone (http://schemas.microsoft.com/ws/2005/05/envelope/none)' does not support adding Message Headers.
I'm just researching this now, so if you know what this error is about, please let me know.
The problem with WCF is that it is so complex, the Exceptions cover so many different errors each and the Exception messages are so vague. From my limited experience, it seems like an error message will say one thing, but it will often be wholly, or partly irrelevant to your actual problem. So I basically kept fixing errors, which unlocked new Exceptions (and I still haven't come to the end of them yet!), but for the purpose of this question, there is an answer.
So it turned out that the original EndpointNotFoundException was actually thrown because there was an unhandled Exception in the AddExportConfirmation service method implementation. Once I had simplified the code (as in the first question update), that particular Exception went away and was replaced with the next one.
My WCF service configuration:
<system.net>
<connectionManagement>
<add address ="*" maxconnection="500"/>
</connectionManagement>
</system.net>
<bindings>
<basicHttpBinding>
<binding name="customBasicHttpBinding"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="StreamedResponse">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="None"/>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="customWebBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceBehaviors>
<behavior name="soapBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553600"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceThrottling maxConcurrentCalls="100"
maxConcurrentInstances="100" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
<services>
<service behaviorConfiguration="soapBehavior" name="Service.Service">
<endpoint name="soap"
address=""
binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding"
contract="ServiceModel.IService"/>
<endpoint
address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
As you can see I set up throttling parameter to handle 100 concurrent instances.
For a test purpose I created dummy method on my interface that looks something like this
[OperationContract]
string Test(){
return "test response time";
}
When I'm trying to call this method, it uses 100 parallel request ats once response time is very bad:
Now running 100 parallel requests...
ResponseTimes: 0,45205P, 10,047P, 0,43304P, 0,86609P, 1,33913P, 0,91409P, 1,34713P, 1,75718P, 1,37414P, 1,80718P, 1,80618P, 2,22622P, 2,64426P, 2,22822P, 2,62626P, 2,68127P, 3,0453P, 3,10731P, 3,47635P, 3,51035P, 3,91039P, 3,94039P, 3,9544P, 4,36844P, 4,34943P, 4,78748P, 4,37144P, 4,82248P, 4,79048P, 5,25052P, 4,81948P, 5,67657P, 5,25253P, 5,71657P, 5,67357P, 6,13761P, 5,70257P, 6,56566P, 6,12361P, 7,0117P, 6,53065P, 7,43674P, 6,9517P, 7,86679P, 7,36974P, 7,81778P, 8,29483P, 8,75988P, 8,71587P, 8,24182P, 8,70187P, 9,16392P, 9,12991P, 9,19492P, 9,57596P, 9,65797P, 10,08201P, 10,45205P, 10,52505P, 10,48905P, 10,9521P, 10,89709P, 11,37714P, 11,81118P, 11,32413P, 11,76418P, 11,83918P, 12,18222P, 12,31723P, 12,60526P, 12,75128P, 13,0423P, 13,17132P, 13,48935P, 13,64836P, 13,91039P, 14,07141P, 14,32843P, 14,48945P, 14,78548P, 14,91149P, 15,20652P, 15,33153P, 15,62856P, 15,75558P, 16,0516P, 16,19262P, 16,48265P, 16,61866P, 16,91169P, 17,05471P, 17,33773P, 17,48375P, 17,74677P, 17,92079P, 18,15782P, 18,34183P, 18,58086P, 18,77388P, 19,0069P,
0 request(s) failed.
Average response time:9,20126
Why are results so bad, I tried to change AppPool Worker Process count but no luck, can anyone tell what I'm missing, what is setting limits?
I'm using WCF 4.0, IIS7.5 on a Windows Server 2008R2 machine.
Thank you
It is difficult to provide much insight regarding communication performance issues without detailed information about the service, configuration and environment. At the least, you may way to provide the service binding, the ServiceBehaviorAttribute and information about the client configuration.
From years of conducting WCF performance testing and optimization, we have seen “similar” issues as you described … despite having 100 concurrent connections, the service does not seem to “respond” efficiently, even though the server resources do not seem busy. In our case, the “delay” was associated with a slow, “cold” startup and the time taken by the .NET thread pool to allocate threads.
The following article discusses our issue:
http://blogs.msdn.com/b/dmetzgar/archive/2011/05/04/wcf-scales-up-slowly-with-bursts-of-work.aspx
Good luck.
I just finished a big, industrial scale WCF project that employed throttling and found that throttling doesn't always yield the results you expect. We set up our WCF web servce on a production-grade virtual server, then we created a test harness that emulated 1000+ virtual clients on a multi-threaded program. Once we were ready, we ran, and re-ran, tests over and over using a bunch of different throttling settings from 1 - 1000, but were surprised by the results.
For instance, you'd think that running your web service with 200 max concurrent connections would be twice as fast as 100 max connections, but that's not what we found for settings for things like:
-max concurrent sessions
-max concurrent calls
-max concurrent instances
In reality, there wasn't much of a performance (callsProcessed/second) difference between MaxConcurrentSessions=10 and MaxConcurrentSessions=1000. The calls processed per second was about the same, only the memory usage was different. Same thing with other throttle settings.
The fastest setting we found for throttling? No setting at all; basically, let the System.ServiceModel library handle everything. That's the fastest that we found after days of testing.
As far as your performance is concerned, what I would do is try and figure out where the bottle necks are. For instance, if your WCF service is using SQL to retrieve data, try eliminating SQL and just return a static dataset and see if your time dramatically improves. If it does, then maybe you need to work on the database side of things. If it doesn't, maybe there's a problem processing your SOAP messages.
I am trying to make a WCF service over basicHttpBinding to be used over https. Here's my web.config:
<!-- language: xml -->
<service behaviorConfiguration="MyServices.PingResultServiceBehavior"
name="MyServices.PingResultService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="defaultBasicHttpBinding"
contract="MyServices.IPingResultService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
...
<bindings>
<basicHttpBinding>
<binding name="defaultBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
...
<behaviors>
<serviceBehaviors>
<behavior name="MyServices.UpdateServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
I am connecting using WCFStorm which is able to retrieve all the meta data properly, but when I call the actual method I get:
The provided URI scheme 'https' is invalid; expected 'http'. Parameter
name: via
Try adding message credentials on your app.config like:
<bindings>
<basicHttpBinding>
<binding name="defaultBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Adding this as an answer, just since you can't do much fancy formatting in comments.
I had the same issue, except I was creating and binding my web service client entirely in code.
Reason is the DLL was being uploaded into a system, which prohibited the use of config files.
Here is the code as it needed to be updated to communicate over SSL...
Public Function GetWebserviceClient() As WebWorker.workerSoapClient
Dim binding = New BasicHttpBinding()
binding.Name = "WebWorkerSoap"
binding.CloseTimeout = TimeSpan.FromMinutes(1)
binding.OpenTimeout = TimeSpan.FromMinutes(1)
binding.ReceiveTimeout = TimeSpan.FromMinutes(10)
binding.SendTimeout = TimeSpan.FromMinutes(1)
'// HERE'S THE IMPORTANT BIT FOR SSL
binding.Security.Mode = BasicHttpSecurityMode.Transport
Dim endpoint = New EndpointAddress("https://myurl/worker.asmx")
Return New WebWorker.workerSoapClient(binding, endpoint)
End Function
Change
from
<security mode="None">
to
<security mode="Transport">
in your web.config file. This change will allow you to use https instead of http
Are you running this on the Cassini (vs dev server) or on IIS with a cert installed? I have had issues in the past trying to hook up secure endpoints on the dev web server.
Here is the binding configuration that has worked for me in the past. Instead of basicHttpBinding, it uses wsHttpBinding. I don't know if that is a problem for you.
<!-- Binding settings for HTTPS endpoint -->
<binding name="WsSecured">
<security mode="Transport">
<transport clientCredentialType="None" />
<message clientCredentialType="None"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
and the endpoint
<endpoint address="..." binding="wsHttpBinding"
bindingConfiguration="WsSecured" contract="IYourContract" />
Also, make sure you change the client configuration to enable Transport security.
I had same exception in a custom binding scenario. Anybody using this approach, can check this too.
I was actually adding the service reference from a local WSDL file. It got added successfully and required custom binding was added to config file. However, the actual service was https; not http. So I changed the httpTransport elemet as httpsTransport. This fixed the problem
<system.serviceModel>
<bindings>
<customBinding>
<binding name="MyBindingConfig">
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap11" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<!--Manually changed httpTransport to httpsTransport-->
<httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
bypassProxyOnLocal="false"
decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
keepAliveEnabled="true" maxBufferSize="65536"
proxyAuthenticationScheme="Anonymous"
realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
useDefaultWebProxy="true" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://mainservices-certint.mycompany.com/Services/HRTest"
binding="customBinding" bindingConfiguration="MyBindingConfig"
contract="HRTest.TestWebserviceManagerImpl" name="TestWebserviceManagerImpl" />
</client>
</system.serviceModel>
References
WCF with custombinding on both http and https
I had the EXACT same issue as the OP. My configuration and situation were identical. I finally narrowed it down to being an issue in WCFStorm after creating a service reference in a test project in Visual Studio and confirming that the service was working. In Storm you need to click on the "Config" settings option (NOT THE "Client Config"). After clicking on that, click on the "Security" tab on the dialog that pops up. Make sure "Authentication Type" is set to "None" (The default is "Windows Authentication"). Presto, it works! I always test out my methods in WCFStorm as I'm building them out, but have never tried using it to connect to one that has already been set up on SSL. Hope this helps someone!
Ran into the same issue, this is how my solution turned out at the end:
<basicHttpsBinding>
<binding name="VerificationServicesPasswordBinding">
<security mode="Transport">
</security>
</binding>
<binding name="VerificationServicesPasswordBinding1" />
</basicHttpsBinding>
I basically replaced every occurrence of Http with Https. You can try adding both of them if you prefer.
If you do this programatically and not in web.config its:
new WebHttpBinding(WebHttpSecurityMode.Transport)
Its a good to remember that config files can be split across secondary files to make config changes easier on different servers (dev/demo/production etc), without having to recompile code/app etc.
For example we use them to allow onsite engineers to make endpoint changes without actually touching the 'real' files.
First step is to move the bindings section out of the WPF App.Config into it's own separate file.
The behaviours section is set to allow both http and https (doesn't seem to have an affect on the app if both are allowed)
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
And we move the bindings section out to its own file;
<bindings configSource="Bindings.config" />
In the bindings.config file we switch the security based on protocol
<!-- None = http:// -->
<!-- Transport = https:// -->
<security mode="None" >
Now the on site engineers only need to change the Bindings.Config file and the Client.Config where we store the actual URL for each endpoint.
This way we can change the endpoint from http to https and back again to test the app without having to change any code.
Hope this helps.
To re-cap the question in the OP:
I am connecting [to a WCF service] using WCFStorm which is able to retrieve all the meta data properly, but when I call the actual method I get:
The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via
The WCFStorm tutorials addresses this issue in Working with IIS and SSL.
Their solution worked for me:
To fix the error, generate a client config that matches the wcf service configuration. The easiest way to do this is with Visual Studio.
Open Visual Studio and add a service reference to the service. VS will generate an app.config file that matches the service
Edit the app.config file so that it can be read by WCFStorm. Please see Loading Client App.config files. Ensure that the endpoint/#name and endpoint/#contract attributes match the values in wcfstorm.
Load the modified app.config to WCFStorm [using the Client Config toobar button].
Invoke the method. This time the method invocation will no longer fail
Item (1) last bullet in effect means to remove the namespace prefix that VS prepends to the endpoint contract attribute, by default "ServiceReference1"
<endpoint ... contract="ServiceReference1.ListsService" ... />
so in the app.config that you load into WCFStorm you want for ListsService:
<endpoint ... contract="ListsService" ... />
I needed the following bindings to get mine to work:
<binding name="SI_PurchaseRequisition_ISBindingSSL">
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
</security>
</binding>
wsHttpBinding is a problem because silverlight doesn't support it!
I've added a "Connected Service" to our project by Visual Studio which generated a default method to create Client.
var client = new MyWebService.Client(MyWebService.Client.EndpointConfiguration.MyPort, _endpointUrl);
This constructor inherits ClientBase and behind the scene is creating Binding by using its own method Client.GetBindingForEndpoint(endpointConfiguration):
public Client(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(Client.GetBindingForEndpoint(endpointConfiguration),
new System.ServiceModel.EndpointAddress(remoteAddress))
This method has different settings for https service and http service.
When you want get data from http, you should use TransportCredentialOnly:
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly;
For https you should use Transport:
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
In my case in web.config I had to change binding="basicHttpsBinding" to binding="basicHttpBinding" in the endpoint definition and copy the relative bindingConfiguration to basicHttpBinding section
<!-- Binding settings for HTTPS endpoint -->
<binding name="yourServiceName">
<security mode="Transport">
<transport clientCredentialType="None" />
<!-- Don't use message -->
</security>
</binding>
My solution, having encountered the same error message, was even simpler than the ones above, I just updated the to basicHttpsBinding>
<bindings>
<basicHttpsBinding>
<binding name="ShipServiceSoap" maxBufferPoolSize="512000" maxReceivedMessageSize="512000" />
</basicHttpsBinding>
</bindings>
And the same in the section below:
<client>
<endpoint address="https://s.asmx" binding="basicHttpsBinding" bindingConfiguration="ShipServiceSoap" contract="..ServiceSoap" name="ShipServiceSoap" />
</client>