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

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.

Related

How to resolve a name conversion failure when sending MSMQ messages

I've recently been following this article on how to set up a 3-party queueing system with MSMQ, wherein the publisher, queue server and subscriber are all on separate systems within an Active Directory domain. I've succeeded in completing Part 1 and the first half of Part 2. However, when I continue with the latter half of Part 2 and enable Transport security, I receive the following error: An error occurred when converting the 'mymsmqservermachine.mydomain.network.ads\private$\Path/To/MyQueuedService.svc' queue path name to the format name: Unrecognized error -1072824300 (0xc00e0014). All operations on the queued channel failed. Ensure that the queue address is valid. MSMQ must be installed with Active Directory integration enabled and access to it is available.
I've verified the following:
Active Directory Integration for MSMQ is enabled on all the machines in the 3-party system, per this StackOverflow post.
The URL to the queue remains exactly the same as it was prior to enabling security, which worked just fine, no parsing errors whatsoever.
I've following the instructions provided by Windows when installing MSMQ here.
The relevant parts of the stack trace I get are:
at System.ServiceModel.Channels.MsmqFormatName.FromQueuePath(String queuePath)
at System.ServiceModel.Channels.MsmqUri.ActiveDirectory.UriToFormatName(Uri uri)
at System.ServiceModel.Channels.MsmqOutputChannel.OpenQueue()
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.MsmqOutputChannel.OpenQueue()
at System.ServiceModel.Channels.MsmqOutputChannel.OnOpenCore(TimeSpan timeout)
at System.ServiceModel.Channels.MsmqOutputChannel.OnBeginOpen(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult.InvokeOpen()
at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult..ctor(CommunicationObject communicationObject, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.CommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.ServiceChannel.OnBeginOpen(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult.InvokeOpen()
at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult..ctor(CommunicationObject communicationObject, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.CommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.BeginCallOnce(TimeSpan timeout, CallOnceManager cascade, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.ServiceChannel.BeginEnsureOpened(TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartEnsureOpen(Boolean completedSynchronously)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishEnsureInteractiveInit(IAsyncResult result, Boolean completedSynchronously)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartEnsureInteractiveInit()
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.Begin()
at System.ServiceModel.Channels.ServiceChannel.BeginCall(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, TimeSpan timeout, AsyncCallback callback, Object asyncState)
at System.ServiceModel.Channels.ServiceChannel.BeginCall(ServiceChannel channel, ProxyOperationRuntime operation, Object[] ins, AsyncCallback callback, Object asyncState)
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2,TArg3](Func`6 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, TArg3 arg3, Object state, TaskCreationOptions creationOptions)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateTask(ServiceChannel channel, ProxyOperationRuntime operation, Object[] inputParameters)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateTask(ServiceChannel channel, 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)
Based on the content of the stack trace, it appears that the failure is coming from resolving the queue name within Active Directory. I've tried the following to attempt to resolve such a failure:
Simplifying the name to contain no periods or slashes (didn't work)
Using a public queue instead of a private queue, in the event that this step was omitted from the original tutorial on MSDN (it wasn't, didn't work)
At this point, I'm out of ideas. Has anybody encountered this error when using WCF with net.msmq bindings before and solved their issue ?
EDIT: When running the following test code from the same machine and same user, I'm able to send a message to the queue perfectly fine:
Me.TestContext.WriteLine("Executing under user '{0}'", WindowsIdentity.GetCurrent().Name)
Dim msg = New System.Messaging.Message()
msg.Body = "This is a test message"
msg.Label = "Test Message"
msg.Formatter = new ActiveXMessageFormatter()
Dim queue = new MessageQueue("FormatName:DIRECT=OS:mymsmqservermachine.mydomain.network.ads\private$\Path/To/MyQueuedService.svc")
queue.Send(msg)
By pure fluke, I stumbled across the solution, and I recorded it in my blog.
The gist of the solution was that I had to add a DNS identity for my WCF endpoint binding in my client:
Dim endpointAddress = New EndpointAddress(queueUri, EndpointIdentity.CreateDnsIdentity(queueUri.Host))
Dim netMsmqBinding = New NetMsmqBinding With
{
.Durable = true,
.ExactlyOnce = false,
.UseActiveDirectory = false,
.Security = New NetMsmqSecurity With
{
.Mode = NetMsmqSecurityMode.Transport
}
}
Return New ChannelFactory(Of ICwteCentralPublishingServiceChannel)(netMsmqBinding, endpointAddress)
I apologize to the world for the Visual Basic code, it's a legacy application and wasn't my choice.

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

Self-hosted WCF 4.5 WsHttpBinding -> 400 Bad Response

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

The I/O operation has been aborted because of either a thread exit or an application request

I'm running some WCF net.tcp services on a high-traffic website.
In my local environment everything worked as expect.
In the production environment, the website works for few minutes then the service throw an exception.
When I stop and start again the service website it works again for few minutes.
Here's the details:
A TCP error (995: The I/O operation has been aborted because of either a thread exit or an application request) occurred while transmitting data.
System.ServiceModel.Channels.SocketConnection.EndRead()
System.ServiceModel.Channels.TracingConnection.EndRead()
System.ServiceModel.Channels.ConnectionStream.ReadAsyncResult.OnAsyncReadComplete(Object state)
System.ServiceModel.Channels.TracingConnection.TracingConnectionState.ExecuteCallback()
System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean haveResult, Int32 error, Int32 bytesRead)
System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
The I/O operation has been aborted because of either a thread exit or an application request
I see the same problem on Win8kR2SP1Web:
System.Runtime.InteropServices.COMException (0x800703E3): The I/O operation has been aborted because of either a thread exit or an application request. (Exception from HRESULT: 0x800703E3)
An error occurred while communicating with the remote host. The error code is 0x800703E3.
The I/O operation has been aborted because of either a thread exit or an application request. (Exception from HRESULT: 0x800703E3)
at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
at System.Web.Hosting.IIS7WorkerRequest.ReadEntityCoreSync(Byte[] buffer, Int32 offset, Int32 size)
at System.Web.HttpRequest.GetEntireRawContent()
at System.Web.HttpRequest.FillInFormCollection()
at System.Web.HttpRequest.get_Form()
at System.Web.Mvc.HttpRequestExtensions.GetHttpMethodOverride(HttpRequestBase request)
at System.Web.Mvc.AcceptVerbsAttribute.IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
at System.Linq.Enumerable.All[TSource](IEnumerable`1 source, Func`2 predicate)
at System.Web.Mvc.ActionMethodSelector.RunSelectionFilters(ControllerContext controllerContext, List`1 methodInfos)
at System.Web.Mvc.ReflectedControllerDescriptor.FindAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.ControllerActionInvoker.FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, String actionName)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionSt ep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
First time in 1 year though ...

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 []