Self-hosted WCF 4.5 WsHttpBinding -> 400 Bad Response - wcf

I'm self-hosting a WCF WSHttpBinding bound service. When running, I can't get any variation on the service call to work. Can you diagnose this problem?
A basic GET from the address bar (multiple browsers) fails with 400 Bad Request. So does $.ajax with GET, POST with 'dataType': 'json' or 'dataType': 'jsonp'. I've tried variations on the base address. Including or omitting the WebInvokeAttribute doesn't make a difference. Whether or not the HTTP Method is matched or mismatched doesn't make a difference.
Setting the service endpoint to a narrower path and then browsing to paths outside of that endpoint appropriately results in an error (about the method not being allowed). Using GET from ajax without jsonp will fail due to cross-site-scripting protections as expected but I can avoid that scenario.
(There are a million versions of this question online. Some seem resolved, but with answers that don't help. Others are unresolved. This is not an exact duplicate of any of them.)
The WCF trace invariably indicates: "There is a problem with the XML that was received from the network." with "The body of the message cannot be read because it is empty" as the inner exception - even for a GET request for which there should be no body (right?). Even if I attempt to POST with json data of '' or '{}', I get still this error exactly.
This code sample is mostly from: http://msdn.microsoft.com/en-us/library/ms730935.aspx, a .Net 4.5 WCF sample. The sample is bigger than necessary and I had to add binding.HostNameComparisonMode = HostNameComparisonMode.Exact; so that Windows would allow it to run without full admin rights. I also played with the relative url (now empty) to test.
Running this and pointing the browser to http://localhost:8000/ is properly serving the MEX/WSDL advertisement. This tells me that the webservice is running and that I am browsing to the right endpoint (plus or minus a service prefix, at least) and that Windows Firewall or permissions are not interfering with the process's ability to open or serve on a port. Yet http://localhost:8000/Ping just gets 400.
If I remember correctly (maybe not though), older versions of WCF and .NET didn't allow or didn't support self-hosted web-like protocols. I believe that's changed. Again, the serving of the MEX data isn't all that different from the custom stuff I want to serve - it's just coming from a different place in the same process.
sdb.IncludeExceptionDetailInFaults = true; seems to have no helpful effect here.
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
namespace WCFWebHost
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8000/");
ServiceHost selfHost = new ServiceHost(typeof(EchoService), baseAddress);
try
{
var binding = new WSHttpBinding();
binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
selfHost.AddServiceEndpoint(typeof(IEcho), binding, "");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
var sdb = selfHost.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;
selfHost.Open();
Console.WriteLine("Open and waiting.");
Console.ReadKey(true);
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
[ServiceContract(Namespace = "http://echo")]
public interface IEcho
{
[OperationContract]
[WebInvoke(
Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "Ping")]
void Ping();
}
public class EchoService : IEcho
{
public void Ping()
{
}
}
}
The web config has this traces.svc configuration added:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Verbose, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\Users\...\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
===
Something that seems odd to me is that the traced exception seems to be coming from the error reporting itself. Is this error in the trace hiding better information about the original failure? Or am I just reading a re-throw wrong?
<Exception>
<ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>There is a problem with the XML that was received from the network. See inner exception for more details.</Message>
<StackTrace>
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference)
at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception)
at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource)
at System.Runtime.ExceptionTrace.AsError(Exception exception)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---> System.Xml.XmlException: The body of the message cannot be read because it is empty.
--- End of inner exception stack trace ---</ExceptionString>
<InnerException>
<Exception>
<ExceptionType>System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The body of the message cannot be read because it is empty.</Message>
<StackTrace>
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetInnerException(Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference)
at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception)
at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource)
at System.Runtime.ExceptionTrace.AsError(Exception exception)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Xml.XmlException: The body of the message cannot be read because it is empty.</ExceptionString>
</Exception>
</InnerException>
</Exception>

WSHttpBinding creates a soap based binding. You cannot access this endpoint using a browser by navigating to the URL. You can access this binding by creating a service proxy or using wcftestclient (for testing). If you are looking for developing a REST endpoint then use webHttpBinding instead of wsHttpBinding.
Here is a quick sample on how to develop REST based service. Here is a post which describes the differences between webHttpBinding & wsHttpBinding.

Call WCF Service exposed with WSHttp binding
web.config Settings
<services>
<service name="MyWcfService.MyService">
<endpoint address="jh" binding="wsHttpBinding" bindingConfiguration="NoSecurity" contract="MyWcfService.IMyService" />
</service>
</services>
html page
//SOAP request generated in order to call the Service method
var whRequest ="<s:Envelope xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\">" +
"<s:Header>" +
"<a:Action s:mustUnderstand=\"1\">http://tempuri.org/IMyService/GetData</a:Action>" +
"<a:MessageID>urn:uuid:7fdde7b6-64c8-4402-9af1-cc848f15888f</a:MessageID>" +
"<a:ReplyTo>" +
"<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>" +
"</a:ReplyTo>" +
"<a:To s:mustUnderstand=\"1\">http://localhost:1415/MyService.svc/jh</a:To>" +
"</s:Header>" +
"<s:Body>" +
"<GetData xmlns=\"http://tempuri.org/\">"+
"<value>9</value>"+
"</GetData>" +
"</s:Body>" +
"</s:Envelope>";
$(document).ready(function () {
$("#btnWCFWSHttp").click(function () {
$.ajax({
type: "POST",
url: "http://localhost:1415/MyService.svc/jh/",
data: whRequest,
timeout: 10000,
contentType: "application/soap+xml",
dataType: "xml",
async: false,
success: function (data, status, xhr) {
$(data).find("GetDataResponse").each(function () {
alert($(this).find("GetDataResult").text());
});
},
error: function (xhr, status, error) {
alert(error);
}
});
});
});

Related

WCF service Unable to establish trust relationship for the SSL/TLS secure channel with authority

I have a WCF service that I want to use to connect to an external provider's API. The Client constructor in my service looks like this:
public partial class SomePortTypeClient : System.ServiceModel.ClientBase<SomeService.ClientPortType>, SomeService.SomePortType
{
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
public SomePortTypeClient(string endpointUrl, TimeSpan timeout, string username, string password) :
base(SomePortTypeClient.GetBindingForEndpoint(timeout), SomePortTypeClient.GetEndpointAddress(endpointUrl))
{
this.ChannelFactory.Credentials.UserName.UserName = username;
this.ChannelFactory.Credentials.UserName.Password = password;
this.ChannelFactory.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
System.Security.Cryptography.X509Certificates.StoreName.Root, System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "11au2i3h3ir3o1748905");
}
The client includes a https binding like this:
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(TimeSpan timeout)
{
var httpsBinding = new BasicHttpsBinding();
httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpsBinding.Security.Mode = BasicHttpsSecurityMode.Transport;
var integerMaxValue = int.MaxValue;
httpsBinding.MaxBufferSize = integerMaxValue;
httpsBinding.MaxReceivedMessageSize = integerMaxValue;
httpsBinding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
httpsBinding.AllowCookies = true;
httpsBinding.ReceiveTimeout = timeout;
httpsBinding.SendTimeout = timeout;
httpsBinding.OpenTimeout = timeout;
httpsBinding.CloseTimeout = timeout;
return httpsBinding;
}
And then the actual implementation of the client and calling the endpoint:
TimeSpan duration = new TimeSpan(0, 1, 0);
SomePortTypeClient someClient = new SomePortTypeClient("https://endpointURL", duration, "username", "password");
var response = someClient.someMethod(someParameter).Result;
I created a CSR in Windows cert manager, and the external provider provided the certificates shown in the picture below which I have imported both into my personal and root store on my local machine. It is the top certificate that I use "SetCertificate" on and locate by thumbprint in my client constructor. This certifiate is linked to the Intermediate CA which is again linked to the Root CA.
So! When I run the code and try to call the endpoint I get the following error:
I'm a bit of a noob when it comes to certificates and WCF services, so I'm not sure what could be wrong here. I have tried using the three different certificates, both from the personal and the root store. I have also tried using just basic authentication and none while also setting the username, password and certificate. The service I'm trying to call is a SOAP service.
UPDATE: It seems the certificate was not signed with the correct private key. I reimported the certificate and the error disappeard, however now I'm getting a new error that just says A security error was encountered when verifying the message. I've looked around and it seems this is often caused by a time difference between the client/server. I'm not sure how to solve this either, so any help is appreciated.
UPDATE: I enabled WCF tracing, here is the stack trace for the exception:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"><EventID>131075</EventID><Type>3</Type><SubType Name="Error">0</SubType><Level>2</Level><TimeCreated SystemTime="2019-11-25T07:12:21.8768782Z" /><Source Name="System.ServiceModel" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="ConsoleApp1" ProcessID="22044" ThreadID="6" /><Channel /><Computer>LAPTOP-U7FDFSNI</Computer></System><ApplicationData><TraceData><DataItem><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>https://learn.microsoft.com/dotnet/framework/wcf/diagnostics/tracing/System-ServiceModel-Diagnostics-ThrowingException</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>ConsoleApp1.exe</AppDomain><Exception><ExceptionType>System.ServiceModel.Security.SecurityNegotiationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Could not establish secure channel for SSL/TLS with authority 'URI'.</Message><StackTrace> at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.OnGetResponse(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.HttpWebRequest.SetResponse(Exception E)
at System.Net.HttpWebRequest.CheckWriteSideResponseProcessing()
at System.Net.ConnectStream.ProcessWriteCallDone(ConnectionReturnResult returnResult)
at System.Net.HttpWebRequest.WriteCallDone(ConnectStream stream, ConnectionReturnResult returnResult)
at System.Net.ConnectStream.CallDone(ConnectionReturnResult returnResult)
at System.Net.ConnectStream.IOError(Exception exception, Boolean willThrow)
at System.Net.ConnectStream.HandleWriteHeadersException(Exception e, WebExceptionStatus error)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.TlsStream.ResumeIOWorker(Object result)
at System.Net.TlsStream.WakeupPendingIO(IAsyncResult ar)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Security.SslState.FinishHandshake(Exception e, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ReadFrameCallback(AsyncProtocolRequest asyncRequest)
at System.Net.AsyncProtocolRequest.CompleteRequest(Int32 result)
at System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(Int32 bytes)
at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace><ExceptionString>System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'URI'. ---&gt; System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
--- End of inner exception stack trace ---</ExceptionString><InnerException><ExceptionType>System.Net.WebException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The request was aborted: Could not create SSL/TLS secure channel.</Message><StackTrace> at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)</StackTrace><ExceptionString>System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)</ExceptionString></InnerException></Exception></TraceRecord></DataItem></TraceData></ApplicationData></E2ETraceEvent>

Routing of Self-Hosted WCF Service

I have a self hosted WCF service that listens on port 80 (the third-party device does not support sending on other ports). I also have two web sites and three Web API base services that are also on port 80 and have been working well. All of these services/sites run using different FQDNs (test-svc1.example.com, test-svc2.example.com, test-site1.example.com, etc..). It is important to note that all the subdomains point to the same IP Address on the server. All of this has been working great until I try and install my service that hosts my WCF service. Once I install that service when I attempt to navigate to either of my two sites I get a page with the following information on it:
.....
You have created a service.
To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
.....
If I stop my WCF based service then my site works fine.
The following is the code that is used to host the WCF service.
public class MyService
{
private const string MyServiceName = "MyService";
private ServiceHost _selfHost;
public void Start()
{
this._selfHost = new ServiceHost(typeof(MyWebService), new Uri(wcf.exampe.com));
try
{
BasicHttpBinding binding = new BasicHttpBinding();
int tempValue = 0;
this._selfHost.AddServiceEndpoint(typeof(IMyServiceContract), binding, MyServiceName);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
this._selfHost.Description.Behaviors.Add(smb);
this._selfHost.Open();
}
catch ( CommunicationException ce )
{
this._selfHost.Abort();
}
}
public void Stop()
{
// Close the ServiceHostBase to shutdown the service.
this._selfHost.Close();
}
}
This code is called by a windows service wrapper. What I need is for this service to be able to run on port 80, but only listen for packets associated with wcf.example.com.
--------- EVENT VIEWER Information
I have enabled debugging and tracing in the Event Viewer to see if that would help me isolate the issue. The following is are a few of the items from there.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Application Server-Applications" Guid="{c651f5f6-1c0d-492e-8ae1-b4efd7c9d503}" />
<EventID>57396</EventID>
<Version>0</Version>
<Level>3</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x2000000000010000</Keywords>
<TimeCreated SystemTime="2013-08-16T20:52:13.956945800Z" />
<EventRecordID>99</EventRecordID>
<Correlation ActivityID="{1E2ADE87-F4FC-4B42-8711-DD49B2F0DB6B}" />
<Execution ProcessID="1716" ThreadID="4828" ProcessorID="0" KernelTime="0" UserTime="3" />
<Channel>Microsoft-Windows-Application Server-Applications/Analytic</Channel>
<Computer>MyComputer</Computer>
<Security UserID="S-1-5-18" />
</System>
<EventData>
<Data Name="data1">System.ServiceModel 4.0.0.0</Data>
<Data Name="data2">System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---> System.Xml.XmlException: The body of the message cannot be read because it is empty. --- End of inner exception stack trace ---</Data>
<Data Name="SerializedException">
<Exception>
<ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
</ExceptionType>
<Message>There is a problem with the XML that was received from the network. See inner exception for more details.
</Message>
<StackTrace> at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth) at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength) at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference) at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception) at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource) at System.Runtime.ExceptionTrace.AsError(Exception exception) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result) at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state) at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state) at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync() at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state) at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult) at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult) at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes) at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---&gt; System.Xml.XmlException: The body of the message cannot be read because it is empty. --- End of inner exception stack trace ---
</ExceptionString>
<InnerException>
<Exception>
<ExceptionType>System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
</ExceptionType>
<Message>The body of the message cannot be read because it is empty.
</Message>
<StackTrace> at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth) at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetInnerException(Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth) at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlTextWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth) at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength) at System.Runtime.Diagnostics.EtwDiagnosticTrace.GetSerializedPayload(Object source, TraceRecord traceRecord, Exception exception, Boolean getServiceReference) at System.Runtime.TraceCore.ThrowingException(EtwDiagnosticTrace trace, String param0, String param1, Exception exception) at System.Runtime.ExceptionTrace.TraceException[TException](TException exception, String eventSource) at System.Runtime.ExceptionTrace.AsError(Exception exception) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result) at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result) at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state) at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state) at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync() at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state) at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult) at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult) at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.ListenerAsyncResult.IOCompleted(ListenerAsyncResult asyncResult, UInt32 errorCode, UInt32 numBytes) at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Xml.XmlException: The body of the message cannot be read because it is empty.
</ExceptionString>
</Exception>
</InnerException>
</Exception>
</Data>
<Data Name="AppDomain">MyService.exe</Data>
</EventData>
</Event>
----------------- End Error
The transport sent a message to 'http://x.x.x.8/data/MyService'.
Handling an exception. Exception details: System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---> System.Xml.XmlException: The body of the message cannot be read because it is empty.
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener1.HttpContextReceivedAsyncResult1.ProcessHttpContextAsync()
HttpGetContext start.
--------- EVENT VIEWER Information
As mentioned before, all of this works fine on my test box when running under Visual Studio, but does not work when run on my production box as a service.
Regards,
Richard O

How to catch exception/fault where message size is larger than accepted by the service (server side)?

At first, I thought if I added an implementation of IDispatchMessageInspector, that perhaps this would intercept the message size before any checking on the limit is done. I soon found, this is not the case. The running service obviously makes sure to enforce this rule on a lower level. Now I am curious if there is a way in which I can capture such an exception on the server level and return a response to the client. Would the an implementation of IErrorHandler as a ServiceBehavior do the trick?
Maybe the more general question is: Can this be tracked at the server level?
It may also be worth noting that I am not in control of the WSDL.
The message size is verified at the lower level - at the transport level.
There isn't a easy way to catch that exception (The IErrorHandling interface provided by WCF to handle exceptions doesn't work at this level).
One way would be to create your own custom wcf transport channel (see here an example)
See below how the generated exception looks like when the quota is exceeded - you can see that this is thrown from the low level (HttpChannelListener).
<ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The maximum message size quota for incoming messages (225) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.</Message>
<StackTrace>
at System.ServiceModel.Channels.HttpInput.ThrowHttpProtocolException(String message, HttpStatusCode statusCode, String statusDescription)
at System.ServiceModel.Channels.HttpInput.ThrowMaxReceivedMessageSizeExceeded()
at System.ServiceModel.Channels.HttpInput.GetMessageBuffer()
at System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.DecodeBufferedMessageAsync()
at System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.BeginParse()
at System.ServiceModel.Channels.HttpInput.BeginParseIncomingMessage(HttpRequestMessage httpRequestMessage, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginParseIncomingMessage(AsyncCallback asynCallback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
The best you can do (and the usual way of monitoring this) is to enable logging at the message level.
http://geekswithblogs.net/mnf/archive/2008/10/03/use-wcf-message-logging.aspx
the problem is that the maxMessageSize properties must be set on both client and server. So if the message is too large to be sent or received on the client side, your server will not know about this.

System.ServiceModel.ProtocolException with two 'parallel' proxies

My web services have been working perfectly, It's hard to tell what I did do that resulted in them crashing from time to time. I added HTTP Basic Authentication and swapped database providers, from ObjectDB to MySQL, so there was a drop in performance but this seems irrelevant.
I have SSL protected Java Metro web services hosted on GlassFish v3.1 with MTOM streaming enabled. I'm calling them with a WCF client. The exception occurs randomly from time to time even when I call the same service with the same parameters.
UPDATE Sometimes it just behaves like it makes a successful call, and then no matter which service I'm calling, even with a helloWorld, I'm getting the exception. If I call only one of the proxies, the calls go just fine, but for eg I get the exception, if I make a call to dataMiningClient and then dataStoreClient. Thread safety?
See:
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.Text = "";
DataStoreWSClient dataStoreClient = getDataStoreClient(email, password);
DataMiningWSClient dataMiningClient = getDataMiningClient(email, password);
byte[] dataSet = File.ReadAllBytes(textBox1.Text);
string dataSetName = Path.GetFileName(textBox1.Text);
long checkSum = getCheckSumForDataSet(dataSet);
//WS Call
try
{
//Example:
//The second time I click on this button,
//this is the point where I get the ProtocolException
bool checkSumResponse = dataStoreClient.checkDataSet(checkSum);
//checkSumResponse was always true when I was debugging this
//So no MTOM streaming involved
if (checkSumResponse)
{
richTextBox1.Text = dataMiningClient.kNearestNeighbour(checkSum, notifyByEmail);
}
else
{
richTextBox1.Text = dataMiningClient.kNearestNeighbourMTOM(dataSetName, notifyByEmail, dataSet);
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
richTextBox1.Text = ex.ToString();
}
dataMiningClient.Close();
dataStoreClient.Close();
}
I do not have any error messages on the server side.
This is the exception message I get:
System.ServiceModel.ProtocolException: The content type multipart/related;start="";type="application/xop+xml";boundary="uuid:d64b0098-0dcb-4da4-a047-d305b55da9f5";start-info="text/xml" of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '--uuid:d64b0098-0dcb-4da4-a047-d305b55da9f5
Content-Id:
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
Content-Transfer-Encoding: binary
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<S:Header>
<To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
<Action xmlns="http://www.w3.org/2005/08/addressing"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
S:mustUnderstand="1">http://webServices/DataStoreWS/checkDataSetResponse</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:1cbcfdc6-01e4-4ddc-960d-a9a2d4e3021a</MessageID>
<RelatesTo xmlns="http://www.w3.org/2005/08/addressin'. sender, EventArgs e) in F:\2.0\WSClient3.5ServiceRef\WSClient3.5\Form1.cs:line 51
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WSClient3._5.DataStore.DataStoreWS.checkDataSet(checkDataSetRequest request)
at WSClient3._5.DataStore.DataStoreWSClient.WSClient3._5.DataStore.DataStoreWS.checkDataSet(checkDataSetRequest request) in F:\Dropbox\Suli\MSc\DIPLOMA_MSc\JavaWSJMX\2.0\WSClient3.5ServiceRef\WSClient3.5\Service References\DataStore\Reference.cs:line 1227
at WSClient3._5.DataStore.DataStoreWSClient.checkDataSet(Int64 checkSum) in F:\Dropbox\Suli\MSc\DIPLOMA_MSc\JavaWSJMX\2.0\WSClient3.5ServiceRef\WSClient3.5\Service References\DataStore\Reference.cs:line 1233
at WSClient3._5.Form1.button1_Click(Object sender, EventArgs e) in F:\Dropbox\Suli\MSc\DIPLOMA_MSc\JavaWSJMX\2.0\WSClie
Client Code:
DataMiningWSClient getDataMiningClient(String username, String password)
{
//IMPORTANT - THIS LINE IS ONLY FOR TESTING PURPOSES!
//This code is for accepting self-signed server certificate
ServicePointManager.ServerCertificateValidationCallback += (sender_ws, cert, chain, sslPolicyErrors) => true;
//instantiate transport binding element, leave the defaults
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
transport.MaxReceivedMessageSize = 2147483647;
transport.AuthenticationScheme = AuthenticationSchemes.Basic;
//instantiate message encoding element, where message version must be Soap11WSAddressing10 to match metro web service requirement.
MtomMessageEncodingBindingElement mtom = new MtomMessageEncodingBindingElement();
mtom.WriteEncoding = System.Text.Encoding.UTF8;
mtom.MessageVersion = MessageVersion.Soap11WSAddressing10;
mtom.MaxBufferSize = 2147483647;
mtom.ReaderQuotas.MaxStringContentLength = 2147483647;
//instantiate transport security binding element, with all the suggested values in app.config
TransportSecurityBindingElement b_element = new TransportSecurityBindingElement();
b_element.DefaultAlgorithmSuite = new Basic128SecurityAlgorithmSuite();
b_element.IncludeTimestamp = true;
b_element.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
b_element.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
b_element.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
//instantiate the custom binding and add the elements created above
CustomBinding customBinding = new CustomBinding();
customBinding.Name = "myOwnPersonalCustomBinding";
customBinding.Elements.Add(b_element);
customBinding.Elements.Add(mtom);
customBinding.Elements.Add(transport);
//instantiate the client
DataMiningWSClient DMclient = new DataMiningWSClient(customBinding, new EndpointAddress(new Uri("https://localhost:8181/DataMiner/DataMiner")));
setCredentials(username, password, DMclient.ClientCredentials);
return DMclient;
}
Any hints what could be the problem here? Please tell me if I should extend this question with more info; I may dig into the WCF message logs.
Reason of ProtocolException: I did NOT configure both proxies with an MtomMessageEncodingBindingElement, however both services were defined with the #MTOM annotation.
After defining it for both proxies everything worked fine:
//instantiate message encoding element, where message version must be Soap11WSAddressing10 to match metro web service requirement.
MtomMessageEncodingBindingElement mtom = new MtomMessageEncodingBindingElement();
mtom.WriteEncoding = System.Text.Encoding.UTF8;
mtom.MessageVersion = MessageVersion.Soap11WSAddressing10;
mtom.MaxBufferSize = 2147483647;
mtom.ReaderQuotas.MaxStringContentLength = 2147483647;

Asynchronous WCF fails with MessageSecurityException when multiple worker processes (Web Garden)

I have a simple WCF service using ws2007HttpBinding which puts in a configurable delay, then returns. The service is configured to be PerCall. The service is hosted on IIS 7.5 on Windoes 2008 Server R2 SP1
I am call this asynchronously via console app using an imported service reference.
I can easily inject 10000 requests and they are all successful. Each request uses a new WCF proxy. The CPU was running about 70%
I wanted to see if adding another worker process would help throughput and utilise the full 100% cpu. I configured it to have 2 worker processes.
When I ran this it began to fail virtually immediately with a MessageSecurityException. Even if I set the number of requsts to 10, it still fails. I noticed that it fails more if the timer in the WCF service is short ( between 10 and 50 ms). A higher delay causes less failures.
It either fails on the proxy.Open() or proxy.Close()
I investigated this and thought it might be related to secure conversation. So I disabled this by
setting
establishSecurityContext="false"
(Is this correct?) I am confused why this would be the case if I am creating a new proxy each time
This dis not seem to make any difference.
When I return the AppPool to have only 1 worker process it works again
Has anybody had the same issue, and managed to get a solution. If so can you post you solution in explicit detail.
The errors received are as follows
In the WCF trace it reported
The incoming message is not part of an existing security session
The exception shown in trace
System.ServiceModel.EndpointNotFoundException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
There was no channel that could accept the message with action 'http://tempuri.org/ILoadedService/RunLoad'.
at System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message)
at System.ServiceModel.Channels.DatagramChannelDemuxer2.ProcessItem(TInnerItem item)
at System.ServiceModel.Channels.DatagramChannelDemuxer2.HandleReceiveResult(IAsyncResult result)
at System.ServiceModel.Channels.DatagramChannelDemuxer2.OnReceiveComplete(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.Channels.ReplyChannel.HelpReceiveRequestAsyncResult.OnReceiveRequest(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.Runtime.InputQueue1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
System.ServiceModel.EndpointNotFoundException: There was no channel that could accept the message with action 'http://tempuri.org/ILoadedService/RunLoad'.
Exception caught on the client
Exception thrown of type [System.ServiceModel.Security.MessageSecurityException] Source [mscorlib]
Exception when receiving response [9] - Message [An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.] StackTrace [
Server stack trace:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at SimpleIISTestClient.SlowClient.ILoadedService.EndRunLoad(IAsyncResult result)
at SimpleIISTestClient.Program.PerfAsynchCallback(IAsyncResult result) in C:\CRF Prototypes\Load\SimpleIISTestClient\Program.cs:line 116]
Inner Exception [9] - Message [The security context token is expired or is not valid. The message was not processed.] StackTrace []