WCF, tipo di restituzione dell’interfaccia e KnownTypes

Sto creando un servizio WCF e sto avendo un sacco di problemi con alcuni problemi di serializzazione. Forse c’è solo 1 modo per farlo, ma mi piacerebbe confermarlo Ecco il mio codice di esempio:

contratti

public interface IAtm { [DataMember] double Latitude { get; set; } [DataMember] double Longitude { get; set; } } [ServiceContract] public interface IAtmFinderService { [OperationContract] ICollection GetAtms(); } 

Implementazione del servizio:

 [KnownType(typeof(Atm))] [KnownType(typeof(List))] [ServiceKnownType(typeof(Atm))] [ServiceKnownType(typeof(List))] public class AtmFinderService : IAtmFinderService { public ICollection GetAtms() { return new List() { new Atm() { Latitude = 1, Longitude = 1 }, new Atm() { Latitude = 2, Longitude = 2 } }; } } 

Ho aggiunto tutti gli attributi KnownType e ServiceKnownType perché pensavo che ci fosse qualcosa che mancava lì. Così ora, ho fatto alcuni test. Ho provato a creare un’app console, utilizzando il metodo “aggiungi riferimento servizio” per rendere VS creare automaticamente il proxy. In questo modo, ottengo una funzione simile

 object[] GetAtms(); 

Quando provo a chiamarlo, ottengo questo errore:

Il messaggio InnerException era ‘Tipo’ WCFTest.Atm ‘con nome contratto dati’ Atm: http: //schemas.datacontract.org/2004/07/WCFTest ‘non è previsto. Prendi in considerazione l’utilizzo di DataContractResolver o aggiungi staticamente i tipi non noti all’elenco dei tipi noti, ad esempio utilizzando l’attributo KnownTypeAttribute o aggiungendoli all’elenco dei tipi noti passati a DataContractSerializer. ‘.

Molto bello … Quindi, penso che il codice generato automaticamente da VS sia una schifezza. Ho apportato le seguenti modifiche al mio servizio (e tutte le relative classi e implementazioni):

 [OperationContract] ICollection GetAtms(); 

Quindi ora sto tornando un tipo concreto. Dopo aver aggiornato il riferimento al servizio, crea una copia della class Atm, con i suoi membri e materiale. Dopo aver chiamato il servizio, la chiamata ha esito positivo. Ho pensato che si trattasse di un cattivo comportamento legato al codice generato automaticamente, quindi ho provato a creare un’applicazione host / client molto semplice. Ho avviato un host di console in ascolto su alcune porte, quindi ho creato un client che utilizza la class ClientBase per effettuare una chiamata al servizio. Stesso comportamento … se il servizio è implementato restituendo un tipo di interfaccia, fallisce. Se lo cambio per restituire il tipo concreto, funziona. Penso di avere qualche problema con gli attributi di KnownType, mi manca qualcosa che il serializzatore non può elaborare. ma non so cosa.

Ok, sono riuscito a sistemarlo Il problema, come vedo, era questo

Dal momento che sto restituendo un’interfaccia e non una class concreta, WCF non sa cosa aspettarsi dall’altra parte. Quindi, può essere qualsiasi cosa. Quando ottiene una lista, è confuso.
Il modo corretto per farlo era aggiungere gli attributi KnownType dove necessario.
Chi ha bisogno di sapere questi tipi? l’implementazione del servizio, per serializzarli e deserializzarli correttamente. Tuttavia, il cliente parla con l’interfaccia del servizio, non con l’implementazione stessa. Ecco perché l’aggiunta dell’attributoKnownType nell’implementazione del servizio non ha funzionato
Il problema è che le interfacce non consentono gli attributi di KnownType, ma consentono gli attributi ServiceKnownType. La soluzione al problema era aggiungere il tipo previsto nel contratto dell’interfaccia di servizio, e voilà, tutto funziona bene e l’uso delle interfacce

  [ServiceContract] [ServiceKnownType(typeof(Atm))] [ServiceKnownType(typeof(List))] public interface IAtmFinderService { [OperationContract] ICollection GetAtms(); }