.net - configurar - ¿Cómo se devuelve un tipo definido por el usuario de un servicio WCF?
wcf endpoint configuration (4)
Tengo un servicio WCF alojado en IIS. La intención es que los clientes realicen una llamada y reciban una clase personalizada que esté definida en otro proyecto / dll. He generado un cliente de servicio usando svcutil.exe. El problema es que este cliente autogenerado contiene una nueva definición parcial / proxy para la clase que estoy tratando de devolver desde el servicio. Ahora arroja un error de conversión entre mi clase personalizada original y la nueva definición parcial en tiempo de compilación. Entonces, ¿cómo devuelve tipos definidos por el usuario de un servicio WCF? Consejo apreciado
Hemos caminado por ese camino en el pasado, y de hecho el problema es que, por supuesto, estas son dos clases diferentes, por lo que tendrá que seguir el enlace provisto por @Rich Reuter;
Sin embargo, hemos aprendido de la peor manera por qué esta es una mala práctica, ya que va contra el tercer principio de SOA: "Los servicios comparten el esquema y el contrato, no la clase".
Por supuesto, el problema no es simplemente no seguir una "regla" establecida por alguien en algún momento, sino que hubo grandes razones para sugerir esto: hemos aprendido que el precio de un acoplamiento tan ajustado entre el servicio y el cliente lo hace es muy difícil de liberar; si el servicio necesita agregar otro campo a esa clase, para dar servicio a otro cliente, el primer cliente podría verse afectado; si el servicio necesita cambiar algo en esa definición de clase (para atender a otro cliente) - el primer cliente se verá nuevamente afectado, y viceversa - el cliente puede afectar el ciclo de vida del servicio.
En proyectos grandes, esto se convierte rápidamente en una enorme carga de mantenimiento.
Si el tipo que desea devolver de su llamada de servicio no está marcado como DataContract
, no podrá devolverlo desde WCF sin proporcionar una copia de ese mismo conjunto a su aplicación cliente.
using System;
using System.ServiceModel;
[ServiceContract]
interface IService
{
[OperationContract]
TimeSpan GetTimeSpan();
}
class Service : IService
{
public TimeSpan GetTimeSpan() { return DateTime.Now.TimeOfDay; }
}
¿Por qué el código anterior funciona entonces? Funciona porque ambos lados de la llamada al servicio tienen System.dll
por lo que ambos conocen el tipo System.TimeSpan
que es el tipo de devolución de OperationContract GetTimeSpan()
.
Aquí hay un ejemplo usando un DataContract
:
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
[ServiceContract]
interface IService
{
[OperationContract]
Contract GetContract();
}
[DataContract]
class Contract
{
[DataMember]
public String MyProperty { get; set; }
}
class Service : IService
{
public Contract GetContract() { return new Contract(); }
}
Ahora ha proporcionado atributos de serialización a una clase que ha definido ( Contract
): esto le permitirá usar svcutil.exe
para crear clases de proxy en su aplicación cliente que serán serializadas y enviadas al servicio WCF.
Ahora, si desea devolver un tipo que no sea un DataContract
, debe proporcionar una copia del ensamblado que contenga ese tipo a su aplicación cliente.
Una de las cosas que tendrá que suceder es que el usuario debe configurar la referencia del servicio para usar los tipos de la DLL en lugar de la clase definida por el proxy - http://msdn.microsoft.com/en-us/library/ bb628653.aspx
Solo para secundar los pensamientos de Yossi / Rich :
- sí, puede agregar una referencia al dll compartido (en lugar de usar la clase proxy generada)
- sí, se frustra gran parte de la intención de los contratos de datos, y si ocurre algún tipo de serialización personalizada, es posible que tenga problemas para extender su servicio
He pasado por este camino antes, y de alguna manera desearía no haberlo hecho. Reextensibilidad / serialización personalizada: debe tener mucho cuidado. Es un poco más fácil si utiliza un serializador previamente enrollado, como protobuf-net (que puede integrarse directamente en WCF, y que está diseñado teniendo en cuenta la extensibilidad), pero no es fácil.
En realidad, una ventaja de compartir las clases es que hace que sea un poco más fácil de probar: dado que tienes el mismo IFoo
todas partes, puedes IFoo
ese IFoo
con posibilidades razonables de éxito. Es más difícil burlarse cuando el proxy se involucra (a medida que cambia más partes móviles entre el código de prueba y el código de producción).