none
Routing of Self-Hosted WCF Service RRS feed

  • Question

  • 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/data));

                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/data.

    Regards,

    Richard O
    • Edited by Richard-O Monday, August 19, 2013 3:57 PM
    Monday, August 19, 2013 3:31 PM

Answers

  • Hi Richard-O,

    So you have a self-hosted (in windows service) WCF service which will share the HTTP 80 port with existing web applications hosted in IIS webserver, correct?

    I'm not sure if you have already reserved the HTTP url namespace for the self-hosted windows service app (for the account used to execute the windows service). If we want to let a self-hosted app share same HTTP port with IIS, but using a concrete sub url, we need to reserve it through HTTP configuration tools (different based on OS version). here are some reference talking on this:

    #Configuring HTTP
    http://blogs.msdn.com/b/drnick/archive/2006/04/14/configuring-http.aspx

    #Configuring HTTP and HTTPS
    http://msdn.microsoft.com/en-us/library/ms733768.aspx

    For windows vista, windows 7 and windows 2008 and later, we can use the netsh.exe tool. For example, suppose we have IIS default site configured on port 80. Then, if we want to have a self-hosted WCF app (via console) which also listen on 80 port at a sub url, we can use the following command to reserve the HTTP URL namespace (so that the console app can open the ServiceHost at the reserved base address).

    netsh http add urlacl url=http://+:80/WCFSimpleApp user=domain/username


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Richard-O Wednesday, August 21, 2013 8:10 PM
    Wednesday, August 21, 2013 8:25 AM
    Moderator

All replies

  • 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>DALDEV01</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. ---&amp;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.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()

    HttpGetContext start.

    All of this works fine on my test box, but the parsing seems to fail on my production system.  I am not sure why that is.  Could I be missing a library, an update, or a setting somewhere?


    Monday, August 19, 2013 4:13 PM
  • Hi Richard-O,

    So you have a self-hosted (in windows service) WCF service which will share the HTTP 80 port with existing web applications hosted in IIS webserver, correct?

    I'm not sure if you have already reserved the HTTP url namespace for the self-hosted windows service app (for the account used to execute the windows service). If we want to let a self-hosted app share same HTTP port with IIS, but using a concrete sub url, we need to reserve it through HTTP configuration tools (different based on OS version). here are some reference talking on this:

    #Configuring HTTP
    http://blogs.msdn.com/b/drnick/archive/2006/04/14/configuring-http.aspx

    #Configuring HTTP and HTTPS
    http://msdn.microsoft.com/en-us/library/ms733768.aspx

    For windows vista, windows 7 and windows 2008 and later, we can use the netsh.exe tool. For example, suppose we have IIS default site configured on port 80. Then, if we want to have a self-hosted WCF app (via console) which also listen on 80 port at a sub url, we can use the following command to reserve the HTTP URL namespace (so that the console app can open the ServiceHost at the reserved base address).

    netsh http add urlacl url=http://+:80/WCFSimpleApp user=domain/username


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Richard-O Wednesday, August 21, 2013 8:10 PM
    Wednesday, August 21, 2013 8:25 AM
    Moderator