Il s’agit d’un service hébergé .svc IIS avec ssl et appartenance.
Mon client wcf rapporte:
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"
Je reçois sur le serveur: System.ArgumentException Cette collection contient déjà une adresse avec le schéma http. Il peut y avoir au plus une adresse par schéma dans cette collection. Nom du paramètre: item
La chose étrange est que cela ne se produit que sur le serveur de production, le même code et le même code config Sur le serveur de développement localhost fonctionnent correctement. Je ne modifie que l'adresse du noeud final et À partir du nom de l'ordinateur. sur www.webdomain.com
plus de trace du serveur
<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"/>
</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>
Le problème est dû à la manipulation de IIS de plusieurs en-têtes d’hôte. Comme blowdart l’a dit: Erreur: cette collection contient déjà une adresse avec le schéma http.
et un peu plus élaboré ici http://forums.silverlight.net/forums/p/12883/274592.aspx
l'utilisation de la première baseAddresses [0] n'est pas une option pour moi car mes basesAddresses étaient http: //localhost/WebServices/OrderService.svchttp: // www. greenjump.nl/WebServices/OrderService.svchttps://vps2051.xlshosting.net/WebServices/OrderService.svc dans cet ordre de parcours que je pourrais faire [1 ] mais je n'aime pas cette dépendance à la configuration.
Il semble que mon problème soit un peu plus complexe en raison de la liaison https. Voici le ServiceHostFactory que j'ai créé:
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);
}
}
Néanmoins, cela semble hacky et devrait être résolu par Microsoft.
Si vous hébergez dans IIS, vous n'avez pas besoin de la section d'adresse de base, car c'est la configuration du site IIS qui la fournit, alors supprimez-la.
Il existe un "problème" lorsque IIS est configuré pour plusieurs en-têtes d'hôte. Dans ce cas, vous devez utiliser une fabrique personnalisée qui supprime toutes les adresses, à l'exception de celle de votre choix. Un exemple simple est
namespace Example
{
public class GenericServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
//return the first...
return new ServiceHost(serviceType, baseAddresses[0]);
}
}
}
Ensuite, vous utiliseriez cela dans votre fichier .svc
<%@ ServiceHost
Service="MyImplementationClass"
Factory="Example.GenericServiceHostFactory"
%>
Deux suppositions: vous avez plusieurs entrées <endpoint address = "" quelque part.
Ils peuvent ne pas avoir les mêmes valeurs, mais ils peuvent résoudre le même nom.
Ou puisqu'il semble que vous utilisiez https: //, utilisez-vous http sur la machine de développement et https sur la version en direct?
Si oui, avez-vous des adresses de points de terminaison distinctes pour les deux? En théorie, vous ne devriez pas faire cela. Vous devriez activer la sécurité du transport sur une adresse de base http, ce qui l'empêchera de pouvoir être appelé autrement que par https.
Techniquement, http et https sont deux schémas http.
J'ai pu résoudre le problème en suivant les étapes ci-dessous à l'aide de Visual Studio 2013:
Allez dans le dossier de votre projet où vous avez votre fichier * .svc
Clic droit sur le fichier * .svc -> Afficher dans le navigateur
Validez si vous êtes capable de parcourir le service
Accédez au dossier de votre projet dans lequel vous avez votre fichier app.config ou à celui où vous souhaitez utiliser le service.
Faites un clic droit sur le projet -> Ajouter -> Référence du service
Cliquez sur Découvrir -> Sous Services. Sélectionnez Service -> Donnez le nom souhaité à la référence de votre service -> Cliquez sur OK.
Il créera "ServiceReference1" sous le dossier "Service References" et créera/mettra à jour automatiquement le fichier app.config
Essayez d’ajouter un préfixe à votre serveur de production dans la configuration Web:
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="https://www.greenjump.nl:443" />
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
Ce serait ajouté à <system.serviceModel>
Et votre point final devrait ressembler à ceci:
<endpoint address="https://www.greenjump.nl:443/WebServices/OrderService.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttps"
contract="SharpShop.Services.IOrderService">
Sinon, vous pouvez toujours surcharger le ServiceFactory comme l’a suggéré un autre commentateur.