glenatron
glenatron

Reputation: 11352

Configuring WCF Service with MSMQ protocol on IIS - Invalid URI: The hostname could not be parsed

I am trying to set up a WCF service on IIS ( IIS7, Windows 7 ) using configured endpoints and, as is typical with IIS configuration, it is a world of hurt. The service works fine working under the debugger on VS2010, but when I come to deploy it I get the following message upon opening http://localhost:9000/MyApplication/_vti_bin/ListData.svc :

[UriFormatException: Invalid URI: The hostname could not be parsed.]
  System.Runtime.AsyncResult.End(IAsyncResult result) +650220
  System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +210733
  System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +166

Interestingly, if I refresh it, the message changes:

[ArgumentException: An item with the same key has already been added.]
   System.Runtime.AsyncResult.End(IAsyncResult result) +650220
   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +210733
   System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +166

I assume the second error is a consequence of the first, so I'm trying to track that down first.

Now, I know what you are thinking: "It would be really great to see a long and boring Web.Config file at this juncture." Your wish is my command:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="loggingenabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="SecurityBehavior" name="MSMQSecuredService.SecuredMSMQService">
        <endpoint address="net.msmq://MyMachine/private/securedqueue"
          binding="netMsmqBinding" bindingConfiguration="SecuredBinding"
          name="EndpointMSMQ" contract="MSMQSecuredService.ISecuredMSMQService">
          <identity>
            <dns value="MyMachine" />
          </identity>
        </endpoint>
<!-- I have tried configuring the endpoint address to everything from the full path to this "/" with no change in outcome -->
        <endpoint address="/" binding="basicHttpBinding" name="EndPointHTTP"
          contract="MSMQSecuredService.ISecuredMSMQService" />
        <endpoint address="mex" binding="mexHttpBinding" name="EndPointIMEX"
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://MyMachine:9000/MyApplication" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SecurityBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True"/>
          <serviceCredentials>
            <serviceCertificate findValue="CertServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
            <clientCertificate>
              <certificate findValue="CertClient" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
              <authentication certificateValidationMode="None"/>
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netMsmqBinding>

        <binding name="SecuredBinding" exactlyOnce="false" receiveErrorHandling="Fault">
          <security mode="Message">
            <message clientCredentialType="Certificate"/>
          </security>
        </binding>
      </netMsmqBinding>

    </bindings>
  </system.serviceModel>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

Obviously enough I have endeavoured to obfuscate exact machine, application and port names, so if there is a slight mismatch there it may not be the problem.

On IIS I have configured the Binding on the site to include net.msmq - my best guess about the problem is that the "bindinginformation" is incorrect - if I set it to the machine name of the current machine I get the above message, if I set it to "localhost" it gives me an ASP.Net server error with the following appearing in the Event Log and WCF Trace files:

The service '/MyApplication/_vti_bin/ListData.svc' does not exist. ---> System.ServiceModel.EndpointNotFoundException: The service '/MyApplication/_vti_bin/ListData.svc' does not exist.

I am guessing that maybe the URI it is complaining about is the hostname in the bindinginformation, but I cannot find any information on what it needs to be or, if localhost is correct, how to dive any deeper into the problem.

Edited to add: With WCF Tracing enabled I see the following pattern occurring:

<Description>MsmqActivation service started scan for queues.</Description>
<AppDomain>/LM/W3SVC/2/ROOT/MyApplication-1-130053972428149879</AppDomain>

Then

<Description>Throwing an exception.</Description><AppDomain>/LM/W3SVC/2/ROOT/My-Application-1-130053972428149879</AppDomain>
<Exception>
  <ExceptionType>System.ServiceModel.EndpointNotFoundException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The service '/MyApplication/_vti_bin/ListData.svc' does not exist.</Message><StackTrace>   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
   at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath, EventTraceActivity eventTraceActivity)
   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><ExceptionString>System.ServiceModel.EndpointNotFoundException: The service '/MyApplication/_vti_bin/ListData.svc' does not exist.</ExceptionString>
</Exception>

Finally we see this:

<Description>MsmqActivation service cannot discover queues.</Description>
<AppDomain>/LM/W3SVC/2/ROOT/MyApplication-1-130053250352242318</AppDomain>
<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/DictionaryTraceRecord">
  <Host>.</Host>
  <PublicQueues>True</PublicQueues>
</ExtendedData>
<Exception>
  <ExceptionType>System.Messaging.MessageQueueException, System.Messaging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</ExceptionType>
  <Message>A workgroup installation computer does not support the operation.</Message>
  <StackTrace>
  at System.Messaging.MessageQueue.GetMachineId(String machineName)
  at System.Messaging.MessageQueueCriteria.set_MachineName(String value)
  at System.Messaging.MessageQueue.GetPublicQueuesByMachine(String machineName)
  at System.ServiceModel.Channels.MsmqBindingMonitor.OnTimer(Object state)
  </StackTrace>
  <ExceptionString>System.Messaging.MessageQueueException (0x80004005): A workgroup installation computer does not support the operation.
     at System.Messaging.MessageQueue.GetMachineId(String machineName)
     at System.Messaging.MessageQueueCriteria.set_MachineName(String value)
     at System.Messaging.MessageQueue.GetPublicQueuesByMachine(String machineName)
     at System.ServiceModel.Channels.MsmqBindingMonitor.OnTimer(Object state)
  </ExceptionString>
</Exception>

Now this final exception looks like it might be the most indicative- the system appears to be looking for a public queue when the queue I am trying to write to is ./private$/MyApplication - so what do I need to change to point it in the right direction?

Upvotes: 1

Views: 2695

Answers (2)

Vahid Ghadiri
Vahid Ghadiri

Reputation: 4076

IIS Just supports Http protocol. If you need to use MSMQ you have to choose other options such as WAS or Self hosting (win forms, WPF or Win service). In table below you can find features that each WCF Hosting Option supports.

enter image description here

Upvotes: 0

Nikolay
Nikolay

Reputation: 3828

I have the same issue and found the solution here - http://vijayvepak.blogspot.ru/2012/09/an-item-with-same-key-has-already-been.html Solution: Go to IIS, go to the website of the webapp. Rightclick –> edit bindings Make sure net.msmq protocol’s binding information is set to localhost

It helped us on all workstations, where we have this bug.

Upvotes: 2

Related Questions