wcf to service
Ejecute WCF ServiceHost con mĂșltiples contratos (8)
¿Me perdí algo, o la solución más simple no se menciona aquí? La solución más simple es esta: no use interfaces múltiples para el servicio web.
Pero eso no significa que todavía pueda tener sus interfaces separadas. Es por eso que tenemos herencia de interfaz.
[ServiceContract]
public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
{
}
La interfaz Meta hereda de todas las otras interfaces.
[ServiceContract]
public interface ISomeOjectService1
{
[OperationContract]
List<SomeOject> GetSomeObjects();
}
[ServiceContract]
public interface ISomeOjectService2
{
[OperationContract]
void DoSomethingElse();
}
Entonces el servicio solo tiene la interfaz Meta.
public class SomeObjectService : IMetaSomeObjectService
{
public List<SomeOject> GetSomeObjects()
{
// code here
}
public void DoSomethingElse()
{
// code here
}
}
Ejecutar un ServiceHost con un solo contrato funciona bien así:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();
Ahora me gustaría agregar un segundo contrato (3º, 4º, ...). Mi primera suposición sería simplemente agregar más puntos finales como este:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
Pero, por supuesto, esto no funciona, ya que en la creación de ServiceHost puedo pasar MyService1 como parámetro o MyService2, así que puedo agregar muchos puntos finales a mi servicio, pero todos tienen que usar el mismo contrato, ya que solo puedo proporcionar una implementación?
Tengo la sensación de que me estoy perdiendo el sentido, aquí. ¿Seguro que debe haber alguna manera de proporcionar una implementación para cada contrato final que agregue, o no?
¿Qué hay de dividirlo con una dirección base y múltiples servicios / contratos debajo de él? No estoy detrás de un developmachine en este momento, pero algo así como:
http://myserver/myservices/serviceA
http://myserver/myservices/serviceB
http://myserver/myservices/serviceC
Cada servicio implementa su propio ServiceContract.
Tu puedes cambiar
public class WcfEntryPoint : IMyService1, IMyService2
a
public partial class WcfEntryPoint : IMyService1
public partial class WcfEntryPoint : IMyService2
Actualmente me encuentro con el mismo problema y he decidido seguir con la implementación a continuación. No estoy seguro de si hay algún problema de rendimiento con tantos contratos de servicio, pero en mi implementación final probablemente tenga entre 10 y 15 contratos de servicio, por lo tanto, alrededor de 10-15 ServiceHosts.
Estoy alojando todos mis servicios de WCF dentro de un solo servicio de Windows.
private void PublishWcfEndpoints()
{
var mappings = new Dictionary<Type, Type>
{
{typeof (IAuthenticationService), typeof (AuthenticationService)},
{typeof(IUserService), typeof(UserService)},
{typeof(IClientService), typeof(ClientService)}
};
foreach (var type in mappings)
{
Type contractType = type.Key;
Type implementationType = type.Value;
ServiceHost serviceHost = new ServiceHost(implementationType);
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
Properties.Settings.Default.ServiceUrl + "/" + contractType.Name);
endpoint.Behaviors.Add(new ServerSessionBehavior());
ServiceDebugBehavior serviceDebugBehaviour =
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;
log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);
serviceHost.Open();
serviceHosts.Add(serviceHost);
}
}
Siéntete libre de comentar sobre este tipo de configuración, y si hay algún problema con ella, especialmente relacionado con el desempeño.
Encontré otra solución para este problema usando una clase RoutingService . Cada contrato debe estar alojado en su propio ServiceHost
, pero puede haber un RoutingService
sobre todos ellos y presentarlos en un "punto final" unificado. También escribí un artículo sobre el proyecto de código al respecto. El código de ejemplo también está disponible en Bitbucket .
Esta respuesta es una respuesta más al comentario en la respuesta aceptada de chilltemp.
Sam, realmente deberías determinar por qué necesitas 10-50 contratos e intentar encontrar otra solución. Miré los estándares de codificación WCF de Juval Lowy (que se encuentran en idesign.net ) y encontré las siguientes referencias:
3 Contratos de servicio ... 4. Evite contratos con un miembro. 5. Esfuércese por tener de tres a cinco miembros por contrato de servicio. 6. No tiene más de veinte miembros por contrato de servicio. Doce es probablemente el límite práctico.
Él no menciona un límite en las implementaciones de contrato (que puedo encontrar), pero no puedo imaginarlo viendo 50 contratos en un servicio como algo que se asemeja a una mejor práctica. Una solución que he encontrado que funciona bien es usar el uso compartido de miembros para funciones similares.
Por ejemplo, si está utilizando el servicio WCF para realizar cálculos matemáticos en 2 valores, puede tener 4 miembros en el lado del servicio: Agregar (x, y), Restar (x, y), Multiplicar (x, y), Divide (x , y). Si combina esto en un miembro más genérico y utiliza un objeto para pasar los datos necesarios, puede reducir fácilmente su número de miembros y aumentar la escalabilidad. Ejemplo: PeformCalculation (obj) donde obj tiene propiedades x, y, y acción (agregar, restar, multiplicar, dividir).
Espero que esto ayude.
La respuesta de chile funcionará si está de acuerdo con los contratos que comparte el servicio. Si quieres que se separen, prueba esto:
host1 = new ServiceHost(typeof(MyService1));
host2 = new ServiceHost(typeof(MyService2));
host1.Open();
host2.Open();
public class MyService1 : IMyService1
{
#region IMyService1
#endregion
}
public class MyService2 : IMyService2
{
#region IMyService2
#endregion
}
Editar: Como Matt publicó, esto requeriría múltiples puntos finales para cada servicio / contrato
Nadie documenta los enteres. Cuando se usa más de uno (como un grupo, desde url común, por ejemplo http) debe usar la misma instancia de enlace (no más), es decir,
Tu muestra:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
debería ser solo un enlace nuevo (), lo he probado a través de http.
servicehost = new ServiceHost(typeof(MyService1));
BasicHttpBinding binding = new BasicHttpBinding();
servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
Estoy totalmente de acuerdo con la clase parcial implementando pocos contratos en pocos archivos.
Necesita implementar ambos servicios (interfaces) en la misma clase.
servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open();
public class WcfEntryPoint : IMyService1, IMyService2
{
#region IMyService1
#endregion
#region IMyService2
#endregion
}
FYI: frecuentemente uso clases parciales para facilitar la lectura de mi código de clase de host:
// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
// IMyService1 methods
}
// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
// IMyService2 methods
}