2009-02-18 29 views
6

Deseo saber cómo configurar tipos conocidos en WCF. Por ejemplo, tengo una clase Person y una clase Employee. La clase Employee es una subclase de la clase Person. Ambas clases están marcadas con un atributo [DataContract].WCF: configuración de tipos conocidos

No quiero codificar el tipo conocido de una clase, como poner un [ServiceKnownType(typeof(Employee))] en la clase Person para que WCF sepa que Employee es una subclase de Person.

Ahora, he añadido a App.config la siguiente configuración XML del huésped:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.runtime.serialization> 
    <dataContractSerializer> 
     <declaredTypes> 
     <add type="Person, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"> 
      <knownType type="Employee, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral, PublicKeyToken=null" /> 
     </add> 
     </declaredTypes> 
    </dataContractSerializer> 
    </system.runtime.serialization> 
    <system.serviceModel> 
    ....... 
    </system.serviceModel> 
</configuration> 

compilé, ejecute el anfitrión, agregó una referencia de servicio al cliente y ha añadido algo de código y ejecutar el cliente. Pero ocurrió un error:

El formateador inició una excepción mientras intentar deserializar el mensaje: Hubo un error al intentar deserializar parámetro http://www.herbertsabanal.net:person. El mensaje InnerException era 'Error en la línea 1 posición 247. Elemento 'http://www.herbertsabanal.net:person' contiene datos del contrato de datos 'http://www.herbertsabanal.net/Data:Employee' . El deserializador no tiene conocimiento de de ningún tipo que se asocie al de este contrato. Añadir el tipo correspondiente a 'empleado' a la lista de tipos conocidos - por ejemplo, por usando el KnownTypeAttribute atributo o mediante la adición a la lista de conocidos tipos pasados ​​a DataContractSerializer '.. Consulte InnerException para obtener más detalles.

A continuación se presentan los contratos de datos:

[DataContract(Namespace="http://www.herbertsabanal.net/Data", Name="Person")] 
    class Person 
    { 
     string _name; 
     int _age; 

     [DataMember(Name="Name", Order=0)] 
     public string Name 
     { 
      get { return _name; } 
      set { _name = value; } 
     } 

     [DataMember(Name="Age", Order=1)] 
     public int Age 
     { 
      get { return _age; } 
      set { _age = value; } 
     } 
    } 


[DataContract(Namespace="http://www.herbertsabanal.net/Data", Name="Employee")] 
    class Employee : Person 
    { 
     string _id; 

     [DataMember] 
     public string ID 
     { 
      get { return _id; } 
      set { _id = value; } 
     } 
    } 

Por cierto, no hizo uso de bibliotecas de clases (WCF bibliotecas de clases o librerías de clases no-WCF) para mi servicio. Simplemente lo codifiqué en el proyecto de host.

Supongo que debe haber un problema en el archivo de configuración (consulte el archivo de configuración anterior). O debo estar perdiendo algo. Cualquier ayuda sería muy apreciada.

+0

sospecho que la configuración solo funciona si se usa una biblioteca de terceros y se hace referencia al servicio. Lo intentaré y volveré a esta pregunta si encuentro algunas respuestas. – jerbersoft

Respuesta

8

Supongo que he encontrado la respuesta ahora.

El archivo de configuración que he publicado citadas es el siguiente:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.runtime.serialization> 
    <dataContractSerializer> 
     <declaredTypes> 
     <add type="Person, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"> 
      <knownType type="Employee, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral, PublicKeyToken=null" /> 
     </add> 
     </declaredTypes> 
    </dataContractSerializer> 
    </system.runtime.serialization> 
    <system.serviceModel> 
    ....... 
    </system.serviceModel> 
</configuration> 

Lo que acaba de agregar era, el espacio de nombres de la clasepersona y la clase Empleado . Y no hay necesidad para los valores ya la versión y Cultura .... La configuración correcta debe ser:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.runtime.serialization> 
    <dataContractSerializer> 
     <declaredTypes> 
     <add type="WCFWithNoLibrary.Person, WCFWithNoLibrary"> 
      <knownType type="WCFWithNoLibrary.Employee, WCFWithNoLibrary" /> 
     </add> 
     </declaredTypes> 
    </dataContractSerializer> 
    </system.runtime.serialization> 
    <system.serviceModel> 
    ....... 
    </system.serviceModel> 
</configuration> 

Ahora es más corto y tiene más sentido. Pero si se utilizan bibliotecas de terceros, entonces se requerirá agregar la versión, cultura, publickeytokens.

+2

Upvote. ¿Tuviste que hacer algo en el lado del cliente .config? – granadaCoder

+1

Tendrá que duplicar la configuración en el cliente para que pueda recibir el nuevo tipo. –

5

Sé que esto fue respondida hace mucho tiempo, pero, otra solución (tal vez más evidente para los futuros programadores):

[KnownType(typeof(SubClass))] 
public class BaseClass 

de Scott

+4

esto no siempre es posible si el subtipo está en un proyecto diferente –

0

Tengo este mensaje de error muy largo también en otro caso. Usé el KnownTypeAttribute y había implementado con éxito una aplicación que usa WCF.RIA para producción. En el segundo lanzamiento, agregué un nuevo subtipo y agregué el correspondiente KnownTypeAttribute (el compilador no lo aceptó sin este atributo, excelente). Sin embargo, lo que el compilador aceptó y lo que se ejecutó en mi máquina no se ejecutó en producción. Solo en producción obtuve el error mencionado anteriormente. Al comparar todos los usos de los subtipos existentes y el nuevo revelé que había olvidado que WCF.RIA requiere el nombre del subtipo que se utilizará en el nombre de un método, como GetMySubTypes. Entonces, si obtiene este error después de haber agregado los atributos, vea si se debe a las convenciones WCF.RIA s.

Cuestiones relacionadas