Indicare le classi da serializzare con KnownType in WCF

di Ugo Lattanzi, in Windows Communication Foundation,

Una delle caratteristiche più interessanti del mondo .NET è sicuramente l'ereditarietà, di cui ne facciamo uso quotidiano nelle nostre applicazioni. Ci sarà sicuramente capitato migliaglia di volte di imbatterci in un Domain Model che fa uso dell'ereditarietà.
Proviamo ad immaginare una situazione simile a quella illustrata dal diagramma seguente:

Ad una prima analisi non vi è nulla di complesso in questo grafo, una semplice classe base astratta con due derivazioni ben distinte.
In un ambiente Service Oriented, un domain model tipo questo può causare dei problemi in fase di serializzazione delle entity, quando (ad esempio) viene restituita una lista di PostBase.
Infatti per un contratto come il seguente:

[ServiceContract(Namespace = "https://www.winfxitalia.com/script/services/serializzation/2008/08/13")]
  public interface IService1
  {
    [OperationContract]
    IList<PostBase> GetPost();
  }

Si può avere un'eccezzione del tipo System.ServiceModel.CommunicationException, simile alla seguente:

There was an error while trying to serialize parameter https://www.winfxitalia.com/script/services/serializzation/2008/08/13:GetPostResult. The InnerException message was 'Type 'WinFxItalia.Script.Serialization.Domain.MediaPost' with data contract name 'MediaPost:http://schemas.datacontract.org/2004/07/WinFxItalia.Script.Serialization.Domain' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details."

Questo problema è dovuto al fatto che in fase di serializzazione il framework si accorge delle diversità dei vari elementi presenti nella lista ma non riesce a convertirli nei tipi concreti (BlogPost e MediaPost nel nostro esempio).

Il problema è facilemente risolvibile andando a decorare la nostra classe base PostBase con l'attributo KnownType presente all'interno System.Runtime.Serialization.
L'attributo è piuttosto semplice e lo snippet seguente mostra come utilizzarlo:

namespace WinFxItalia.Script.Serialization.Domain
{
  using System;
  using System.Runtime.Serialization;
  
  [Serializable]
  [DataContract]
  [KnownType(typeof(BlogPost))]
  [KnownType(typeof(MediaPost))]
  public abstract class PostBase
  {
    [DataMember]
    public int ID { get; set; }
    
    [DataMember]
    public DateTime CreationDate { get; set; }
    
    [DataMember]
    public string AuthorName { get; set; }
    
    [DataMember]
    public string Title { get; set; }
    
    [DataMember]
    public string Description { get; set; }
  }
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi