none
Exception in WebScriptClientGenerator when using an AJAX enabled WCF Service RRS feed

  • Question

  •  

    Hi,

    We have a website that uses a few AJAX enabled WCF services. Once in a while, when a browser is requesting the script client using a request to myservice.svc/js, the following exception occurs:

    System.ArgumentException: Specified value has invalid Control characters. Parameter name: value.
    This exception is followed by: System.ServiceModel.CommunicationObjectAbortedException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.  The communication object, System.ServiceModel.InstanceContext, cannot be used for communication because it has been Aborted.

    Once this exception occurs, the javascript proxy faults...... Can anbody help me?






    <E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
      <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <EventID>131076</EventID>
        <Type>3</Type>
        <SubType Name="Error">0</SubType>
        <Level>2</Level>
        <TimeCreated SystemTime="2008-12-17T18:01:35.6718402Z" />
        <Source Name="System.ServiceModel" />
        <Correlation ActivityID="{25e31d3a-f279-44ea-832b-8524aab5b33b}" />
        <Execution ProcessName="w3wp" ProcessID="4056" ThreadID="16" />
        <Channel/>
        <Computer>VIL-WEB-01</Computer>
      </System>
      <ApplicationData>
        <TraceData>
          <DataItem>
            <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
              <TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Diagnostics.TraceHandledException.aspx</TraceIdentifier>
              <Description>Handling an exception.</Description>
              <AppDomain>/LM/W3SVC/1795423524/Root-11-128740103618672585</AppDomain>
              <Exception>
                <ExceptionType>System.ArgumentException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
                <Message>
                  Specified value has invalid Control characters.
                  Parameter name: value
                </Message>
                <StackTrace>
                  at System.Net.WebHeaderCollection.CheckBadChars(String name, Boolean isHeaderValue)
                  at System.Net.WebHeaderCollection.Add(String name, String value)
                  at System.Collections.Specialized.NameValueCollection.Add(NameValueCollection c)
                  at System.ServiceModel.Channels.HttpRequestMessageProperty.get_Headers()
                  at System.ServiceModel.Description.WebScriptClientGenerator.Get(Message message)
                  at SyncInvokeGet(Object , Object[] , Object[] )
                  at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp;amp; outputs)
                  at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
                </StackTrace>
                <ExceptionString>
                  System.ArgumentException: Specified value has invalid Control characters.
                  Parameter name: value
                  at System.Net.WebHeaderCollection.CheckBadChars(String name, Boolean isHeaderValue)
                  at System.Net.WebHeaderCollection.Add(String name, String value)
                  at System.Collections.Specialized.NameValueCollection.Add(NameValueCollection c)
                  at System.ServiceModel.Channels.HttpRequestMessageProperty.get_Headers()
                  at System.ServiceModel.Description.WebScriptClientGenerator.Get(Message message)
                  at SyncInvokeGet(Object , Object[] , Object[] )
                  at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp;amp; outputs)
                  at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
                </ExceptionString>
              </Exception>
            </TraceRecord>
          </DataItem>
        </TraceData>
      </ApplicationData>
    </E2ETraceEvent>



    <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="2008-12-19T12:33:04.0932620Z" />
        <Source Name="System.ServiceModel" />
        <Correlation ActivityID="{0dd6ef6f-8d47-4528-b22a-f8beffa8e63d}" />
        <Execution ProcessName="w3wp" ProcessID="3196" ThreadID="15" />
        <Channel/>
        <Computer>VIL-WEB-01</Computer>
      </System>
      <ApplicationData>
        <TraceData>
          <DataItem>
            <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
              <TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
              <Description>Throwing an exception.</Description>
              <AppDomain>/LM/W3SVC/1795423524/Root-7-128741633767844467</AppDomain>
              <Source>System.ServiceModel.InstanceContext/13779405</Source>
              <Exception>
                <ExceptionType>System.ServiceModel.CommunicationObjectAbortedException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
                <Message>The communication object, System.ServiceModel.InstanceContext, cannot be used for communication because it has been Aborted.</Message>
                <StackTrace>
                  at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposed()
                  at System.ServiceModel.Dispatcher.InstanceBehavior.EnsureInstanceContext(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp;amp; rpc)
                  at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
                  at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
                  at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
                  at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
                  at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
                  at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
                  at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
                  at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
                  at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
                  at System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
                  at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
                  at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback)
                  at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
                  at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
                  at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
                  at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
                  at System.ServiceModel.PartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
                  at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
                  at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
                  at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
                  at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
                  at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
                  at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
                  at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
                  at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
                </StackTrace>
                <ExceptionString>System.ServiceModel.CommunicationObjectAbortedException: The communication object, System.ServiceModel.InstanceContext, cannot be used for communication because it has been Aborted.</ExceptionString>
              </Exception>
            </TraceRecord>
          </DataItem>
        </TraceData>
      </ApplicationData>
    </E2ETraceEvent>

    Monday, December 22, 2008 10:10 AM

Answers

  • This is a known bug on .NET Fx 3.5, which was fixed on .NET 4.0. Basically, the first exception you get is a valid one - some client is sending a request with a header with invalid characters (per the HTTP specification), so WCF is rejecting the request. The main bug is that after that, the proxy endpoint gets into a bad state (the second exception you see). I don't know whether the fix from SP1 makes WCF accept those requests (i.e., ignore the bad headers) or not, but at least it won't leave the endpoint in that bad state.

    If you can't upgrade yet, you can change your .svc file as shown below, that should prevent the "/js" endpoint from going into a bad state when a bad request arrives.

    <%@ServiceHost language=c# Debug="true" Service="<the_actual_service_name>" Factory="MyTest.MyServiceHostFactory" %>  
       
    namespace MyTest  
    {  
        using System;  
        using System.ServiceModel;  
        using System.ServiceModel.Activation;  
        using System.ServiceModel.Web;  
        using System.ServiceModel.Dispatcher;  
        using System.ServiceModel.Description;  
        using System.ServiceModel.Channels;  
       
        public class MyServiceHostFactory : ServiceHostFactory  
        {  
            protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)  
            {  
                return new MyServiceHost(serviceType, baseAddresses);  
            }  
        }  
        public class MyServiceHost : ServiceHost  
        {  
            public MyServiceHost(Type serviceType, params Uri[] baseAddresses)  
                : base(serviceType, baseAddresses)  
            {  
            }  
            protected override void InitializeRuntime()  
            {  
                base.InitializeRuntime();  
                foreach (ChannelDispatcher cd in this.ChannelDispatchers)  
                {  
                    bool isJs = false;  
                    foreach (EndpointDispatcher ep in cd.Endpoints)  
                    {  
                        string epAddress = ep.EndpointAddress.Uri.ToString();  
                        if (epAddress.EndsWith("/js") || epAddress.EndsWith("/jsdebug"))  
                        {  
                            isJs = true;  
                        }  
                    }  
                    if (isJs)  
                    {  
                        cd.ErrorHandlers.Add(new MyErrorHandler());  
                    }  
                }  
            }  
        }  
        public class MyErrorHandler : IErrorHandler  
        {
            #region IErrorHandler Members  
            public bool HandleError(Exception error)  
            {  
                return true;  
            }  
       
            public void ProvideFault(Exception error, MessageVersion version, ref Message fault)  
            {  
                FaultException<string> ex = new FaultException<string>(error.Message);  
                MessageFault messageFault = ex.CreateMessageFault();  
                fault = Message.CreateMessage(version, messageFault, "http://my.fault/");  
            }
            #endregion  
        }  
    }  
     
    • Marked as answer by chris-wcf Tuesday, December 23, 2008 8:52 AM
    • Edited by Carlos Figueira Friday, June 25, 2010 10:19 PM
    Monday, December 22, 2008 3:24 PM

All replies

  • Hi,

     The exception states that there are illegal control characters used in the HTTP headers. You could try to log the incoming requests including the headers, and correlate the log against the service log to check which characters that causes the exception.

     --larsw

    Lars Wilhelmsen | Senior Consultant | Miles, Norway | MCTS WCF | http://larswilhelmsen.com/
    Monday, December 22, 2008 11:10 AM
    Moderator
  • Hi Lars,

    I think you are right... we do think there is a relation with the requests http headers.

    But how to deal with this problem?
    1) Is there a solution to prevent having the exception "
    Specified value has invalid Control characters. Parameter name: value"?
    2) How to recover the faulted automatically generated javascript proxy of the webservice?

    Regards,
    Chris
    Monday, December 22, 2008 12:39 PM
  • Hi again,

     I'm no JS expert, but I believe you will need to create a wrapper around the wcf proxy, and check the state of the proxy before you invoke a service operation. if the proxy is in a faulted state, you will need to recreate the wrapped proxy.

     --larsw
    Lars Wilhelmsen | Senior Consultant | Miles, Norway | MCTS WCF | http://larswilhelmsen.com/
    Monday, December 22, 2008 12:42 PM
    Moderator
  • This is a known bug on .NET Fx 3.5, which was fixed on .NET 4.0. Basically, the first exception you get is a valid one - some client is sending a request with a header with invalid characters (per the HTTP specification), so WCF is rejecting the request. The main bug is that after that, the proxy endpoint gets into a bad state (the second exception you see). I don't know whether the fix from SP1 makes WCF accept those requests (i.e., ignore the bad headers) or not, but at least it won't leave the endpoint in that bad state.

    If you can't upgrade yet, you can change your .svc file as shown below, that should prevent the "/js" endpoint from going into a bad state when a bad request arrives.

    <%@ServiceHost language=c# Debug="true" Service="<the_actual_service_name>" Factory="MyTest.MyServiceHostFactory" %>  
       
    namespace MyTest  
    {  
        using System;  
        using System.ServiceModel;  
        using System.ServiceModel.Activation;  
        using System.ServiceModel.Web;  
        using System.ServiceModel.Dispatcher;  
        using System.ServiceModel.Description;  
        using System.ServiceModel.Channels;  
       
        public class MyServiceHostFactory : ServiceHostFactory  
        {  
            protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)  
            {  
                return new MyServiceHost(serviceType, baseAddresses);  
            }  
        }  
        public class MyServiceHost : ServiceHost  
        {  
            public MyServiceHost(Type serviceType, params Uri[] baseAddresses)  
                : base(serviceType, baseAddresses)  
            {  
            }  
            protected override void InitializeRuntime()  
            {  
                base.InitializeRuntime();  
                foreach (ChannelDispatcher cd in this.ChannelDispatchers)  
                {  
                    bool isJs = false;  
                    foreach (EndpointDispatcher ep in cd.Endpoints)  
                    {  
                        string epAddress = ep.EndpointAddress.Uri.ToString();  
                        if (epAddress.EndsWith("/js") || epAddress.EndsWith("/jsdebug"))  
                        {  
                            isJs = true;  
                        }  
                    }  
                    if (isJs)  
                    {  
                        cd.ErrorHandlers.Add(new MyErrorHandler());  
                    }  
                }  
            }  
        }  
        public class MyErrorHandler : IErrorHandler  
        {
            #region IErrorHandler Members  
            public bool HandleError(Exception error)  
            {  
                return true;  
            }  
       
            public void ProvideFault(Exception error, MessageVersion version, ref Message fault)  
            {  
                FaultException<string> ex = new FaultException<string>(error.Message);  
                MessageFault messageFault = ex.CreateMessageFault();  
                fault = Message.CreateMessage(version, messageFault, "http://my.fault/");  
            }
            #endregion  
        }  
    }  
     
    • Marked as answer by chris-wcf Tuesday, December 23, 2008 8:52 AM
    • Edited by Carlos Figueira Friday, June 25, 2010 10:19 PM
    Monday, December 22, 2008 3:24 PM
  • Hi Carlos,

    The install of .NET 3.5 SP1 did not do the trick for me.

    Your code sample does help. A request which has a header with invalid control characters still does not work. But the proxy endpoint does not go into a bad state!!!! So all other valid requests will be processed. This is a big improvement for me.

    Regards,
    Chris

    Tuesday, December 23, 2008 8:52 AM