Pregunta

Tengo lo siguiente:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

Cuando ejecuto el método Get me sale el siguiente error:

Hubo un error al intentar serializar parámetro http://tempuri.org/:GetResult.El InnerException mensaje fue, "Tipo", PPS.Núcleo.DomainModel.Apoyo.Acción.ActionResult`1[ [PPS.Núcleo.DomainModel.SportProgram.ISportProgram, PPS.Núcleo.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' con contrato de datos nombre de 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action'no es el esperado.Añadir cualquier tipo no se conoce de forma estática en la lista de tipos conocidos - por ejemplo, mediante el uso de la KnownTypeAttribute atributo o añadiéndolos a la lista de tipos conocidos pasado a DataContractSerializer.'.Por favor, consulte InnerException para obtener más detalles.

A partir de este error que puedo ver que se puede resolver ActionResult pero no puede resolver ISportProgram a pesar de que he ServiceKnownType(typeof(ActionResult < SportProgram >)) en mi interfaz de servicio...

Nota esta es la Referencia de código auxiliar que se genera este aspecto, por lo que puedo ver que los tipos conocidos están siendo llevados a través correctamente:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

¿Por qué esta mal????Nota su obtención a través del servicio de WCF correctamente...pero se produce la excepción cuando el resultado se devuelve.

Por último ActionResult se parece a esto:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

Saludos Anthony

¿Fue útil?

Solución

Bueno, creo que este es otro caso de la SOA vsLa programación orientada a objetos "desajuste de impedancia".Las dos son muy distintos.

En WCF, todos los que se pasa desde el cliente al servidor se pasa como serializado mensajes - no hay referencias están siendo utilizados.

Esto significa:todo lo que usted desea serializar en el cliente, enviar a través del servidor, y deserializar y el uso de la misma, debe ser hormigón - usted no puede pasar alrededor de las interfaces, se puede utilizar "no resuelto" genéricos - es necesario explicar.Básicamente, todo lo que se pasa desde el cliente a través de la conexión con el servidor deben ser expressable en el esquema XML.

Esto tiene muchas implicaciones:

  • no hay interfaces - usted no puede pasar alrededor de interfaces - que necesita para trabajar con tipos concretos
  • no "automático" de la herencia - sólo se puede definir una clase base y el paso de las clases derivadas basadas en ella -, las que deben ser specificied demasiado (que es lo que la ServiceKnownType atributo es)
  • no hay ninguna opción de genéricos - de nuevo, usted necesita usar el hormigón de los tipos de cambio

Esto puede sonar como un montón de restricciones - pero es porque WCF está usando todos los mensajes de comunicación - que no puede lidiar con refereces, la herencia, los genéricos etc.- es necesario explicar.

Así que realmente no tengo una respuesta para usted por sí mismo - yo creo que necesita replantearse su estrategia y cambiar la forma en que su cliente y el servidor intercambian información a través de WCF.

Marc

PS:Hice un poco más de investigación, y contrario a toda mi entender, parece ser que hay una forma para serializar cualquier cosa que se basa en una interfaz y/o clase base abstracta a través de la red, mientras que usted puede estar seguro de que es siempre única .NETA en cualquiera de los extremos del alambre (es decir,es no interoperable con, por ejemplo,Java).

Ver Aarón Skonnard blog sobre el NetDataContractSerializer y otro blog y sin embargo, otro muestra cómo utilizar el NetDataContractSerializer a ser capaz de pasar alrededor de cosas como IPerson como parámetros a los métodos.

Otros consejos

Este es uno de los problemas que se resuelven con la ServiceStack.NET - Mi Open Source Web .NET y MONO El marco de servicios.

Servicio de pila fue fuertemente influenciado por patrón de transferencia de Martin Fowler datos de objeto , ya que le permite simplemente utilizar DTO para definir sus servicios web - es decir, la forma en SOA:.)

evito que esta limitación es inherente a WCF mediante la generación de mi propia de WSDL que se comporte como se puede esperar que lo hagan. Como un beneficio de la sustitución / modelo de ServiceContract configuración compleja de WCF - Los servicios web SOAP también funciona en MONO - ver la demostración en vivo .

Es una cuestión de edad ya pesar de que la respuesta aceptada es totalmente correcto, yo stumpled sobre esto en la búsqueda de un problema similar y pensé que podría compartir mis experiencias. Es a menudo un dolor de cabeza, pero es posible utilizar los genéricos combinados con interfaces con WCF. Aquí está un ejemplo de trabajo de otra aplicación (similar) que he hecho:

[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
public interface IService : 
{
    [OperationContract]
    ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);
}

public interface ICollectionWrapper<TModel>
{
    int TotalCount { get; set; }
    IEnumerable<TModel> Items { get; set; }
}

[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
    [DataMember]
    public int TotalCount { get; set; }
    [DataMember]
    public IEnumerable<TModel> Items { get; set; }
}

public class CompanyDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OrganizationDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

La clave aquí es utilizar la combinación de KnownType y ServiceKnownType.

Así que en su caso se puede hacer algo como esto:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic.
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

[KnownType(typeof(SportProgram))] // Actual implementation here.
public class ActionResult<T>
{
    // Other stuff here
    T FooModel { get; set; }
}

Esto funciona si usted tiene un contrato compartido (acceso a la interfaz de servicio real) y consumir el contrato con ChannelFactory<ISportProgramBl>. No sé si funciona con un servicio de referencia.

Sin embargo, parece que hay algunos problemas con la puesta en práctica como se mencionó aquí:

WCF Con una interfaz y un modelo genérico

Y otra pregunta similar hecha y contestada aquí:

tipos de retorno genéricos con params tipo de interfaz en WCF

devolver un IList de T. Es tal vez que el sistema ha problemas de averiguar lo que T es.

No está seguro de si está bien para volver una interfaz en lugar de un tipo.

¿Está especificamos las interfaces de los objetos y no tipos concretos?

PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>

Editar:

Lo que estoy diciendo es que son todos los tipos de hormigón que está pasando en los medicamentos genéricos (incluidos en el objeto secundario a través de interfaces) que se pasa en la lista de tipos conocidos. Hemos tenido problemas serialasation en los que no se conocen todos los tipos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top