“A registration already exists for URI” when hosti

2019-03-20 03:22发布

问题:

I am trying to host the same service inside the same website using two endpoints one HTTP and the other HTTPS.

The problem is I can happily call one service (whichever I call first works) but then call to the other fails until I iisreset and try again. SO I can happily call both but one at a time until a process recycle.

I have exhausted (or I think I have) all relevant Q&A and documents that I could find and none of them seem to help me. The level of documentation of MSDN regarding these cases (which should be faily common) is appalling and nothing works as it seems.

I have used Host/BaseAddresses/BaseAddress with no luck and whenever I used it, I get another error (cannot find an HTTPS scheme).

I have folder called Secure which is enabled for HTTPS inside IIS.

I have disabled mex so no metadata allowed which I got passed previous errors.

Anyone got a clue? I am cluless...

  <service name="Namespace.MyService" behaviorConfiguration="MyBehaviour">
    <host>
      <baseAddresses>
      </baseAddresses> 
    </host> 
    <endpoint address="http://localhost/Services/MyService.svc/MyService"
              name="MyService"   binding="wsHttpBinding"
              bindingConfiguration="myWsHttpBinding" contract="Namespace.IMyService" />

    <endpoint address="https://localhost/Services/Secure/MySslService.svc/MySslService"
              name="MySslService"   binding="basicHttpBinding"
              bindingConfiguration="MySslServiceBinding" contract="Namespace.IMyService" />
  </service>

.....

   <behavior name="MyBehaviour">
      <custom1/>
      <custom2/>
      <serviceMetadata httpGetEnabled="false" />
      <serviceDebug includeExceptionDetailInFaults="false"/>
      <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="CustomProvider"/>
      <serviceCredentials>
        <serviceCertificate findValue="Some" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />

        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="SomeClass, SomeDll"/>
      </serviceCredentials>
    </behavior>

Original error is:

A registration already exists for URI 'http://localhost/Services/....'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: A registration already exists for URI 'http://localhost/Services/....'.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[InvalidOperationException: A registration already exists for URI
System.ServiceModel.Channels.UriPrefixTable1.RegisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, TItem item) +320 System.ServiceModel.Channels.HttpTransportManager.Register(TransportChannelListener channelListener) +380
System.ServiceModel.Channels.TransportManager.Open(TransportChannelListener channelListener) +816
System.ServiceModel.Channels.TransportManagerContainer.Open(SelectTransportManagersCallback selectTransportManagerCallback) +121
System.ServiceModel.Channels.HttpChannelListener.OnOpen(TimeSpan timeout) +125
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
System.ServiceModel.Channels.DatagramChannelDemuxer
2.OnOuterListenerOpen(ChannelDemuxerFilter filter, IChannelListener listener, TimeSpan timeout) +606
System.ServiceModel.Channels.SingletonChannelListener`3.OnOpen(TimeSpan timeout) +91
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +375

Here is the WCF Trace log error:

The ChannelDispatcher at 'http://localhost/Services/...' with contract(s) '"IMyService"' is unable to open its IChannelListener. System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath) System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath) System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest() System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest() System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state) System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state) System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state) System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

回答1:

OK, I fixed my problem. The issue was I was under impression that I had to create a secure folder in IIS and put the .svc file in there to guarantee SSL transmission. It turned out that it is not the case and all I had to do was to use the same .svc file and just define 2 endpoints:

<endpoint address="http://localhost/Services/MyService.svc/MyService"
          name="MyService"   binding="wsHttpBinding"
          bindingConfiguration="myWsHttpBinding" contract="Namespace.IMyService" />

<endpoint address="https://localhost/Services/MyService.svc/MySecureService"
          name="MySslService"   binding="basicHttpBinding"
          bindingConfiguration="MySslServiceBinding" contract="Namespace.IMyService" />


回答2:

It's possible the nested directories are confusing IIS - I have had this happen before although not in the WCF context. Try changing the endpoint addresses to:

address="http://localhost/MyService"
address="https://localhost/MySslService"

Can you try hosting the application from a console app instead of IIS? I'm pretty certain IIS is causing your problem somehow but this might confirm it.

If it's possible, I'd also try to isolate the problem by removing some of the configuration detail - eg bindingConfiguration and behaviorConfiguration.

Obviously these are just debugging steps I'd perform (you may have already) to try and isolate the problem - sorry I haven't got a full answer.