views:

1880

answers:

5

It's a .svc IIS hosted service with ssl and membership.

My wcf client reports:

System.ServiceModel.ServiceActivationException was unhandled
  Message="The requested service, 'https://www.greenjump.nl/WebServices/OrderService.svc' could not be activated. See the server's diagnostic trace logs for more information."
  Source="mscorlib"

On the server I get: System.ArgumentException This collection already contains an address with scheme http. There can be at most one address per scheme in this collection. Parameter name: item

The strange thing is this only happens on the production server, the same code and config on the localhost development server works fine. I only change the endpoint address and from computer name to www.webdomain.com

more server trace

<ExceptionType>
  System.ArgumentException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
</ExceptionType>
<Message>
  This collection already contains an address with scheme http.  There can be at most one address per scheme in this collection.
  Parameter name: item
</Message>
<StackTrace>
  at System.ServiceModel.UriSchemeKeyedCollection.InsertItem(Int32 index, Uri item)
  at System.Collections.Generic.SynchronizedCollection`1.Add(T item)
  at System.ServiceModel.UriSchemeKeyedCollection..ctor(Uri[] addresses)
  at System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri[] baseAddresses)
  at SharpShop.Web.StructureMap.StructureMapServiceHost..ctor(Type serviceType, Uri[] baseAddresses)
  at SharpShop.Web.StructureMap.StructureMapServiceHostFactory.CreateServiceHost(Type serviceType, Uri[] baseAddresses)
  at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses)
  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String normalizedVirtualPath)
  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)
  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
  at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath)
  at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
  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>

config:

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttps">
          <readerQuotas maxStringContentLength="128000"/>
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None"/>
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" >
      <baseAddressPrefixFilters>
        <add prefix="https://www.greenjump.nl"/&gt;
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WsHttpWithAuthBehavior">
          <serviceMetadata httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                                roleProviderName="AspNetSqlRoleProvider"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
              membershipProviderName="AspNetSqlMembershipProvider" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="WsHttpWithAuthBehavior" name="SharpShop.Services.OrderService">
        <endpoint address="https://www.greenjump.nl/WebServices/OrderService.svc" 
                  binding="wsHttpBinding"
                  bindingConfiguration="wsHttps"
                  contract="SharpShop.Services.IOrderService">
          <identity>
            <dns value="www.greenjump.nl" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
A: 

Two guesses: you've got multiple <endpoint address="" entries in there somewhere.

They might not have the same values but they might resolve to the same name.

Or since it looks like you're using https://, do you use http on the dev machine and https on the live one?

If so, do you have separate endpoint addresses for both? In theory you shouldn't do this - you'd enable transport security on an http base address, which will prevent it from being able to be called on anything other than https.

Technically http and https are both http schemes.

Andras Zoltan
only one endpoint, and on de dev machine I also use httpsdid a search solution just to be sure, no other endpoints found.It works in devserver I only replace domain name and endpoint location on production
Medo
looking at the config - have you tried removing the explicit 'address=' from your main service's endpoint? You don't need to specify a base address if the service will 'begin' at the .svc file.
Andras Zoltan
A: 

Try adding a prefix to your production server in ther web config:

<serviceHostingEnvironment>
  <baseAddressPrefixFilters>
    <add prefix="https://www.greenjump.nl:443" />
  </baseAddressPrefixFilters>
</serviceHostingEnvironment>

This would be added to <system.serviceModel>

And your endpoint should look like this:

   <endpoint address="https://www.greenjump.nl:443/WebServices/OrderService.svc" 
              binding="wsHttpBinding"
              bindingConfiguration="wsHttps"
              contract="SharpShop.Services.IOrderService">

Otherwise you can always overload the ServiceFactory like one of the other commentators suggested

Waleed Al-Balooshi
A: 

This is my wcf config, waleeds tip didn't work and should not be different on production or dev. right?

config moved to main question at the top.
Medo
In the IIS in your production machine, do you have multiple bindings setup for the application? Are they using different ports? If so, then try adding port 80 to both the endpoint address and the prefix.
Waleed Al-Balooshi
could you move this configuration to the main body of your answer so that it can all go together?
Andras Zoltan
@waleed The website uses multiple bindings on port 80 (3) and one on 443 https.The webservice should use https only, so should I do this instead of adding port 80: <add prefix="https://www.greenjump.nl:443"/> and<endpoint address="https://www.greenjump.nl:443/WebServices/OrderService.svc" I'm a little bit slow as this is production I can't do it quickly.
Medo
h t t p://www. was automatically converted to link by stackoverflow
Medo
@Medo I forgot that you were using https. So, you would do port 443. I edited my original answer to show this
Waleed Al-Balooshi
+1  A: 

If you're hosting in IIS you don't need the base address section - as it's IIS's site configuration that provides it - so remove that section.

There is a "problem" when IIS is configured for multiple host headers though, in which case you need to use a custom factory which removes all the addresses aside from the one you want. A simple example is

namespace Example
{
    public class GenericServiceHostFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, 
                                                         Uri[] baseAddresses)
        {
            //return the first...
            return new ServiceHost(serviceType, baseAddresses[0]);
        }
    }
} 

Then you would use that in your .svc file

<%@ ServiceHost 
    Service="MyImplementationClass"
    Factory="Example.GenericServiceHostFactory"
%>
blowdart
thanks I was working in that direction will post my result.
Medo
A: 

The problem is caused by IIS handling of multiple host headers. Like blowdart said here. error: This collection already contains an address with scheme http.

and somewhat more elaborate here http://forums.silverlight.net/forums/p/12883/274592.aspx

using the first baseAddresses[0] is not an option for me because my baseAddresses were http://localhost/WebServices/OrderService.svc http://www.greenjump.nl/WebServices/OrderService.svc https://vps2051.xlshosting.net/WebServices/OrderService.svc in this order of course I could do [1] but I don't like this configuration dependency.

It seems my problem is somewhat more complex due to the https binding, this is the ServiceHostFactory I came up with:

 public class MyServiceHostFactory : ServiceHostFactory
    {

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            Uri webServiceAddress = baseAddresses[0]; //default to first

            if (HttpContext.Current != null) //this only works when aspNetCompatibilityEnabled=true
            {
                string host = HttpContext.Current.Request.Url.Host;
                var goodAddress = baseAddresses.FirstOrDefault(a => a.Host == host);//try to find address with same hostname as request
                if(goodAddress!=null)
                {
                    webServiceAddress = goodAddress;
                }
                Type[] sslServices = { typeof(OrderService)  };//add all https services here
                if (sslServices.Any(s => s == serviceType))
                {
                    UriBuilder builder = new UriBuilder(webServiceAddress);
                    builder.Scheme = "https";
                    builder.Port = 443; //fails if you use another port
                    webServiceAddress = builder.Uri;
                }
            }
            return new ServiceHost(serviceType, webServiceAddress);
        }
    }

Still this feels hacky, and should be solved by microsoft.

Medo
@Medo Did you try adding the port to the endpoint and the base prefix? That was one solution so that you wouldn't need to do this custom factory.
Waleed Al-Balooshi