Siguiendo con las ayuditas a mis rivales en el concurso Es la hora de los Puños , voy a exponer un error común que nos podemos encontrar al intentar publicar el servicio WCF en un servidor compartido, una configuración muy habitual en nuestros hostings.
El error:
Esta colección ya contiene una dirección con el esquema http. Sólo puede haber una dirección por esquema en esta colección.
El Problema:
El servidor web IIS solo permite una sola dirección base por esquema (HTTP) y eso para un entorno compartido es un verdadero problema, esto ya está solucionado en IIS 7.0 y framework 4.0 con el atributo multipleSiteBindingsEnabled en el elemento serviceHostingEnvironment.
Posible solución para versiones anteriores:
Para poder hospedar un servicio WCF con un extremo web en un servidor IIS hay que especificar la clase WebServiceHostFactory en el archivo .svc
[sourcecode language=»XML»]
<ServiceHost Language="C#" Debug="true" Service="KillBits.Fight"
CodeBehind="Fight.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" >
[/sourcecode]
O en el fichero de configuración estableciendo el binding webHttpBinding
[sourcecode language=»xml»]
<endpoint address="http://www.lonetcamp.com" binding="webHttpBinding" contract="KillBits.IFight">
[/sourcecode]
Podemos crear nuestro propio HostFactory heredando de WebServiceHostFactory o WebScriptServiceFactory dependiendo si queremos facilitar el acceso desde script de cliente o solo ASP.NET.
[sourcecode language=»csharp»]
public class CustomHostFactory : WebScriptServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
Uri[] newUri;
if (baseAddresses.Length > 1)
newUri = new Uri[] {
new Uri("http://www.lonetcamp.com/KillBits/Fight.svc")};
else
{
newUri = new Uri[] { baseAddresses[0]};
}
return base.CreateServiceHost(serviceType, newUri);
}
}
[/sourcecode]
Este ejemplo detecta si existe más de una baseAddresss y si es así utiliza el creado especialmente para mi servicio y si solo hay uno utiliza ese “ejemplo mejorable”.
lo único que tenemos que hacer es especificar que el servicio utilice nuestro factoy en vez de el por defecto para que funcione perfectamente la publicación.
[sourcecode language=»xml»]
<ServiceHost Language="C#" Debug="true" Service="KillBits.Fight"
CodeBehind="Fight.svc.cs" Factory="KillBits.CustomHostFactory">
[/sourcecode]