2010-03-24 3 views
4

J'ai un petit service Web de test pour émuler quelque chose d'étrange que je remarque dans une application du monde réel. Comme la démo montre le même comportement que l'application, je vais utiliser la démo pour la brièveté. En bref Mon fichier d'interface de service ressemble à ceci (comme vous pouvez le voir, il s'agit du service WCF par défaut créé par VS2008 mais j'ai ajouté une nouvelle méthode publique (GetOtherType()) et deux nouvelles classes en bas (SomeOtherType et SomeComplexType). SomeOtherType gère une liste générique de type SomeComplexTypeType non exposé par le service WCF

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

namespace WCFServiceTest 
{ 

    [ServiceContract] 
    public interface IService1 
    { 
     [OperationContract] 
     string GetData(int value); 

     [OperationContract] 
     CompositeType GetDataUsingDataContract(CompositeType composite); 

     [OperationContract] 
     SomeOtherType GetOtherType(); 

    } 


    [DataContract] 
    public class CompositeType 
    { 
     bool boolValue = true; 
     string stringValue = "Hello "; 

     [DataMember] 
     public bool BoolValue 
     { 
      get { return boolValue; } 
      set { boolValue = value; } 
     } 

     [DataMember] 
     public string StringValue 
     { 
      get { return stringValue; } 
      set { stringValue = value; } 
     } 
    } 

    [DataContract] 
    public class SomeOtherType 
    { 
     public List<SomeComplexType> Items { get; set; }  
    } 

    [DataContract] 
    public class SomeComplexType 
    { 

    } 
} 

Mon service est mis en œuvre comme suit

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

namespace WCFServiceTest 
{ 

    public class Service1 : IService1 
    { 


     #region IService1 Members 

     public string GetData(int value) 
     { 
      throw new NotImplementedException(); 
     } 

     public CompositeType GetDataUsingDataContract(CompositeType composite) 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 

     #region IService1 Members 


     public SomeOtherType GetOtherType() 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 
    } 
} 

Le problème que j'ai est que si j'inclure une référence de service à ce service dans un ASP. Application Web NET, je ca Ne voyez pas SomeComplexType via intellisense. L'erreur est liée au type ou à l'espace de noms introuvable. Cependant, SomeOtherType peut être trouvé (je suppose que le type est un type de retour d'une des méthodes publiques). Ai-je raison de penser que je ne peux pas exposer un type à partir d'un service WCF si ce type n'apparaît pas dans la signature de méthode d'une de mes méthodes publiques (type de retour ou argument)? Si oui, comment serais-je capable d'itérer sur les éléments dans une instance de SomeOtherType sur le client?

Merci beaucoup et j'espère que c'est clair.

Simon

+0

C'est vraiment étrange. Pourquoi définissez-vous vos contrats de données et le service lui-même dans un endroit? Aussi, est-ce dans le fichier SVC ou dans un fichier .cs séparé? – Slavo

Répondre

4

Le problème que j'ai est que si je inclure une référence de service à ce service dans une application Web ASP.NET , Je ne peux pas voir SomeComplexType via IntelliSense. L'erreur concerne le type ou l'espace de noms est introuvable. Cependant, SomeOtherType peut être trouvé (Je suppose que le type est un type de retour de l'une des méthodes publiques).

Suis-je raison de penser que je ne peux pas exposer un type d'un service WCF si ce type ne figure pas dans la méthode signature d'un de mes méthodes publiques (ou l'autre type de retour ou argument)? Si alors, comment serais-je en mesure d'itérer sur les éléments à l'intérieur d'une instance de SomeOtherType sur le client?

Vous êtes tout à fait raison - votre SomeComplexType est jamais utilisé dans l'une des méthodes de service, et il est également jamais taggés comme [DataMember] dans l'un des types qui sont en effet utilisés comme paramètres dans vos méthodes de service.Par conséquent, du point de vue de WCF, ce n'est pas nécessaire, et n'apparaîtra pas dans le WSDL/XSD pour le service.

Comme Graham a déjà signalé - vous utilisez le SomeComplexType en un seul endroit:

[DataContract] 
public class SomeOtherType 
{ 
    public List<SomeComplexType> Items { get; set; }  
} 

mais étant donné que l'élément Items n'est pas marqué comme [DataMember], (et donc le type qu'il utilise) ne sera pas inclus dans le WSDL/XSD de votre service. Comme les Items ne sont pas marqués DataMember, ils ne figureront pas non plus dans votre message WCF sérialisé, donc vous n'aurez plus jamais besoin de parcourir cette collection :-)

Alors très probablement, ce que vous voulez vraiment, c'est ajoutez simplement l'attribut [DataMember] à votre propriété Items; alors il sera inclus dans le WSDL/XSD, tout comme le SomeComplexType.

+0

Merci à Graham et marc_s. Tous les deux ont répondu à la question mais ont marqué marc_s comme réponse car la réponse plus complète pourrait être utile à quelqu'un d'autre. Merci encore tout le monde –

1

Je ne suis pas du tout un expert sur ce sujet, donc tout comme un coup de feu dans le bleu: DataContracts vides sont jetés par la WCF? Essayez d'exposer quoi que ce soit dans ComplexDataType (certains int suffisent) et voyez si cela change quelque chose.

Aussi, je crois que vous pouvez vérifier la disponibilité du type en utilisant le wcftestclient intégré (vous devez activer l'échange de métadonnées pour cela).

2

Vous avez besoin du l'attribut [DataMember] sur votre propriété SomeOtherType.Items, à savoir

[DataMember] 
public List<SomeComplexType> Items { get; set; } 
1

Nous pouvons utiliser le type connu dans le service afin d'être exposé de la classe et de ses membres quand il n'est pas utilisé dans la signature du contrat d'exploitation directement ou indirectement.

0

Pour les types pour lesquels vous souhaitez simplement qu'il soit disponible du côté client, même s'il n'est pas utilisé, la classe d'attributs ci-dessous est pratique pour le rendre disponible côté client.

[KnownType(typeof(SomeComplexType))]