2014-06-11 6 views
5

con WCF, assumono la seguente interfaccia di servizio:WCF non riesce in silenzio per deserializzare lista se i tipi di elementi non corrispondono

[ServiceContract] 
public interface IForDataTypeA 
{ 
    [OperationContract] 
    List<DataTypeA> GetValues(); 
} 

[DataContract] 
public class DataTypeA { } 

Questo è come è definito sul lato server (servizio host).

Ora, qualcuno, senza accesso al codice sorgente del server, tenta di utilizzare questo servizio WCF. Egli definisce l'interfaccia del servizio stesso, ma accidentalmente cambia il nome del tipo di dati a DataTypeB:

[ServiceContract] 
public interface IForDataTypeA 
{ 
    [OperationContract] 
    List<DataTypeB> GetValues(); 
} 

[DataContract] 
public class DataTypeB { } 

Quando lui ora chiama GetValues() (via ChannelFactory<IForDataTypeA>) lista restituita sarà sempre vuoto ma non viene generata un'eccezione .

C'è un modo per far sì che WCF lanci un'eccezione quando gli elementi nell'elenco non possono essere deserializzati (invece di restituire una lista vuota)?


Ecco il codice completo per riprodurre il problema:

using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.ServiceModel; 

namespace TestProj 
{ 
    [DataContract] 
    public class DataTypeA { } 

    [DataContract] 
    public class DataTypeB { } 

    [ServiceContract] 
    public interface IForDataTypeA 
    { 
     [OperationContract] 
     List<DataTypeA> GetValues(); 
    } 

    [ServiceContract(Name = "IForDataTypeA")] 
    public interface IForDataTypeB 
    { 
     [OperationContract] 
     List<DataTypeB> GetValues(); 
    } 

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
    internal class ServiceImpl : IForDataTypeA 
    { 
     public List<DataTypeA> GetValues() 
     { 
      return new List<DataTypeA> 
      { 
       new DataTypeA(), 
       new DataTypeA(), 
      }; 
     } 
    } 

    class Program 
    { 
     static void Main() 
     { 
      var serviceHost = new ServiceHost(new ServiceImpl()); 
      var binding = new NetTcpBinding(); 
      var endpointUrl = "net.tcp://127.0.0.1:5555/MyService"; 

      serviceHost.AddServiceEndpoint(typeof(IForDataTypeA), binding, endpointUrl); 
      serviceHost.Open(); 

      var channelFactory = new ChannelFactory<IForDataTypeB>(binding, endpointUrl); 
      var channel = channelFactory.CreateChannel(); 

      List<DataTypeB> values = channel.GetValues(); 
      // values will always be empty 
     } 
    } 
} 
+1

Questa è una caratteristica di controllo delle versioni. Ti permette di cambiare la definizione del servizio senza rompere i chiamanti. Un giorno sarai grato per questo. D'altra parte la tua richiesta è totalmente valida come aiuto per il debug. – usr

+0

Idealmente l'interfaccia di servizio deve essere condivisa con i client. Cosa succede se dai il nome a DataContract ["Nome =" TipoA "], provato questo? –

+1

@AjayKelkar Sì, questo funzionerà. (Poteva anche rinominare la classe.) Ma non è questo il punto. Il punto è che lo sviluppatore ha cambiato il nome * per errore * ma non viene rilevato alcun errore. –

risposta

0

Penso this video almeno spiega perché si verifica il problema. Ciò è dovuto alla retrocompatibilità.

Forse this post ti aiuterà a risolverlo

+2

Le domande non devono consistere solo di collegamenti, ma se il sito si interrompe, provare ad aggiungere un sommario del contenuto alla risposta: – jAC

+0

Grazie, quello era il mio primo post. Farò meglio da ora in poi! –

+1

Puoi ancora correggerlo modificando;) – jAC

Problemi correlati