2011-08-27 2 views
-1

OK ... J'ai regardé sur le Web et trouvé deux solutions possibles à mon problème de ne pas pouvoir renvoyer un type IEnumerable dans un service WCF .Net 4.0.IEnumerable et WCF - encore une fois

Voir le lien ci-dessous. C'est exactement ce que j'obtiens lorsque j'exécute l'outil WCF Test Client et que j'essaie d'invoquer une méthode.

https://connect.microsoft.com/wcf/feedback/details/336696/ienumerable-t-serialization-bug

Rappelez-vous, pour être sûr qu'il n'y a rien de mal avec mon service web, je suis en mesure de retourner un type de cet objet pour un seul enregistrement, mais pas un IEnumerable.

Les deux solutions que j'ai essayées, montrées ci-dessous ne fonctionnent pas pour moi. J'ai la même erreur. Ça me rend fou. Je sais quel est le problème, j'ai suivi les étapes pour contourner le problème, mais je reçois toujours la même erreur.

Comment puis-je résoudre ce problème?

C'est la première solution que j'ai essayée: Notez que j'ai même essayé de supprimer le "ToList" et "ToArray" sur la dernière instruction dans chacune des méthodes parce que c'est déjà impliqué.

Interface

[OperationContract] 
     IList<Priority> GetPriorities(); 

Méthode

public IList<Priority> GetPriorities() 
     { 
      YeagerTechEntities DbContext = new YeagerTechEntities(); 

      IList<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList(); 

      CloseConnection(DbContext); 

      return priority.ToList(); 
     } 

Ceci est la deuxième solution I essayé:

Interface

[OperationContract] 
     Priority[] GetPriorities(); 

Méthode

public Priority[] GetPriorities() 

     { 
      YeagerTechEntities DbContext = new YeagerTechEntities(); 

      Priority[] priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToArray(); 

      CloseConnection(DbContext); 

      return priority.ToArray(); 
     } 

Ici c'est avec une liste au lieu d'un IList qui ne fonctionne toujours pas.

Interface

[OperationContract] 
     List<Priority> GetPriorities(); 

Méthode

public List<Priority> GetPriorities() 
     { 
      YeagerTechEntities DbContext = new YeagerTechEntities(); 

      List<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList(); 

      CloseConnection(DbContext); 

      return priority.ToList(); 
     } 

Notez que la méthode ci-dessous fonctionne très bien lors de l'extraction un seul objet à la place d'une liste. L'erreur entière msg du client de test wcf pour la première méthode dans cette publication est la suivante. Quelle est la résolution afin de pouvoir renvoyer une liste d'objets?

Echec de l'appel du service. Causes possibles: Le service est hors ligne ou inaccessible; la configuration côté client ne correspond pas au proxy; le proxy existant est invalide. Reportez-vous à la trace de la pile pour plus de détails. Vous pouvez essayer de récupérer en démarrant un nouveau proxy, en restaurant la configuration par défaut ou en actualisant le service.

Une erreur s'est produite lors de la réception de la réponse HTTP à http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/. Cela peut être dû à la liaison de point de terminaison de service n'utilisant pas le protocole HTTP. Cela peut également être dû à l'abandon d'un contexte de requête HTTP par le serveur (probablement en raison de l'arrêt du service). Voir les journaux du serveur pour plus de détails.

trace de pile du serveur: à System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException (WebException WebException, HttpWebRequest demande, HttpAbortReason abortReason) à System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply (timeout TimeSpan) à System.ServiceModel.Channels.RequestChannel.Request (message du message, délai d'attente TimeSpan) à System.ServiceModel.Channels.ClientReliableChannelBinder 1.RequestClientReliableChannelBinder 1.OnRequest (canal TRequestChannel, un message du message, délai d'attente TimeSpan, maskingMode maskingMode) à System.ServiceModel.Channels. ClientReliableChannelBinder 1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode) at System.ServiceModel.Channels.ClientReliableChannelBinder 1.Request (Message message, TimeSpan timeout) à System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request (message du message, délai d'attente TimeSpan) à System.ServiceModel.Dispatcher.RequestChannelBinder.Request (Message message, délai d'attente TimeSpan) à System.ServiceModel.Channels.ServiceChannel. Call (String action, Boolean oneway, opération ProxyOperationRuntime, Object [] ins, Object [] outs, TimeSpan timeout) à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService (IMethodCallMessage methodCall, opération ProxyOperationRuntime) à System.ServiceModel.Channels. ServiceChannelProxy.Invoke (message IMessage)

Exception relancée à [0]: à System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage (IMessage reqMsg, IMessage retMsg) à System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData & MSGDATA, le type Int32) à IYeagerTechWcfService.GetPriorities() à YeagerTechWcfServiceClient.GetPriorities()

exception interne: La connexion sous-jacente a été fermée: une erreur inattendue s'est produite lors de la réception. à System.Net.HttpWebRequest.GetResponse() à System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply (TimeSpan timeout)

exception interne: Impossible de lire les données de la connexion de transport: Une connexion existante a été fermé de force par l'hôte distant. à System.Net.Sockets.NetworkStream.Read (Byte [] tampon, décalage Int32, taille Int32) à System.Net.PooledStream.Read (Octet [] tampon, décalage Int32, taille Int32) à System.Net. Connection.SyncRead (HttpWebRequest demande, Boolean userRetrievedStream, Boolean probeRead)

exception interne: Une connexion existante a été fermée force par l'hôte distant au tampon System.Net.Sockets.Socket.Receive (byte [], Int32 décalé , Taille Int32, SocketFlags socketFlags) à System.Net.Sockets.NetworkStream.Read (tampon Byte [], décalage Int32, taille Int32)

J'ai modifié mes classes (voir ci-dessous), mais Je reçois toujours la même erreur exacte.

Sûrement, il doit sûrement y avoir quelqu'un qui a déjà essayé cela avant de recevoir un objet d'Entity Framework et de le renvoyer comme un IEnumerable. Je suis très frustré par cela. S'il vous plaît aidez-moi ...

Basé sur mon post précédent, mes classes sont exactement les mêmes avec les changements suivants. J'ai essayé deux méthodes.

Veuillez vous reporter aux premier et deuxième scénarios séparément.

Premier scénario pour l'interface

j'ai essayé en utilisant seulement la classe client, puis une déclaration IEnumerable de celui-ci.

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

namespace YeagerTechWcfService 
{ 
//[ServiceKnownType(typeof(YeagerTechModel.Customer))] 
[ServiceKnownType(typeof(IEnumerable<YeagerTechModel.Customer>))] 
[ServiceContract] 
public interface IYeagerTechWcfService 
{ 

[OperationContract] 
IEnumerable<Customer> GetCustomers(); 

[OperationContract] 
Customer GetCustomerID(Int16 customerid); 

Il réside dans mon projet YeagerTechModel dans la même solution référencée par mon service Web (l'autre projet dans la même solution).

Premier scénario pour objet client

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

namespace YeagerTechModel 
{ 
[Serializable] 
[DataContract] 
public partial class Customer 
{ 
public Customer() 
{ 
this.Projects = new HashSet<Project>(); 
} 

[DataMember] 
public short CustomerID { get; set; } 

[Required] 
[StringLength(50)] 
[DataType(DataType.EmailAddress)] 
[DataMember] 
public string Email { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Company { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string FirstName { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string LastName { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Address1 { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Address2 { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string City { get; set; } 

[StringLength(2)] 
[DataType(DataType.Text)] 
[DataMember] 
public string State { get; set; } 

[StringLength(10)] 
[DataType(DataType.Text)] 
[RegularExpression(@"^\d{5}(-\d{4})?$")] 
[DataMember] 
public string Zip { get; set; } 

[StringLength(12)] 
[DataType(DataType.PhoneNumber)] 
public string HomePhone { get; set; } 

[StringLength(12)] 
[DataType(DataType.PhoneNumber)] 
[DataMember] 
public string CellPhone { get; set; } 

[StringLength(100)] 
[DataType(DataType.Url)] 
[DataMember] 
public string Website { get; set; } 

[StringLength(50)] 
[DataType(DataType.EmailAddress)] 
[DataMember] 
public string IMAddress { get; set; } 

[DataMember] 
public System.DateTime CreatedDate { get; set; } 

[DataMember] 
public Nullable<System.DateTime> UpdatedDate { get; set; } 

public virtual ICollection<Project> Projects { get; set; } 

} 

scénario deuxième pour l'interface:

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

namespace YeagerTechWcfService 
{ 
[ServiceContract] 
public interface IYeagerTechWcfService 
{ 

[OperationContract] 
IEnumerable<Customer> GetCustomers(); 

[OperationContract] 
Customer GetCustomerID(Int16 customerid); 

Deuxième scénario pour objet client

J'ai essayé d'utiliser simplement la classe client et puis une déclaration IEnumerable au bas de la est classe.

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

namespace YeagerTechModel 
{ 
[KnownTypeAttribute("KnownTypes")] 
[Serializable] 
[DataContract] 
public partial class Customer 
{ 
public Customer() 
{ 
this.Projects = new HashSet<Project>(); 
} 

[DataMember] 
public short CustomerID { get; set; } 

[Required] 
[StringLength(50)] 
[DataType(DataType.EmailAddress)] 
[DataMember] 
public string Email { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Company { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string FirstName { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string LastName { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Address1 { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string Address2 { get; set; } 

[StringLength(50)] 
[DataType(DataType.Text)] 
[DataMember] 
public string City { get; set; } 

[StringLength(2)] 
[DataType(DataType.Text)] 
[DataMember] 
public string State { get; set; } 

[StringLength(10)] 
[DataType(DataType.Text)] 
[RegularExpression(@"^\d{5}(-\d{4})?$")] 
[DataMember] 
public string Zip { get; set; } 

[StringLength(12)] 
[DataType(DataType.PhoneNumber)] 
public string HomePhone { get; set; } 

[StringLength(12)] 
[DataType(DataType.PhoneNumber)] 
[DataMember] 
public string CellPhone { get; set; } 

[StringLength(100)] 
[DataType(DataType.Url)] 
[DataMember] 
public string Website { get; set; } 

[StringLength(50)] 
[DataType(DataType.EmailAddress)] 
[DataMember] 
public string IMAddress { get; set; } 

[DataMember] 
public System.DateTime CreatedDate { get; set; } 

[DataMember] 
public Nullable<System.DateTime> UpdatedDate { get; set; } 

public virtual ICollection<Project> Projects { get; set; } 

static Type[] KnownTypes() 
{ 
return new Type[] { typeof(IEnumerable<Customer>) }; 
} 

} 

J'ai essayé:

return customer; 
return customer.ToList(); 
return customer.ToArray(); 


public IEnumerable<Customer> GetCustomers() 
{ 
YeagerTechEntities DbContext = new YeagerTechEntities(); 

IEnumerable<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0); 

CloseConnection(DbContext); 

return customer; 
} 

Le problème semble être un problème de sérialisation en essayant de passer de nouveau l'objet client qui fait partie d'un modèle Entity Framework. Il doit y avoir une méthode documentée pour renvoyer un objet de ce type dérivé d'un modèle Entity Framework.

Où est-ce ????

Voici la dernière de ce que j'ai essayé et je reçois toujours la même erreur exacte ....

namespace YeagerTechWcfService 
{ 
    [ServiceContract] 
    public interface IYeagerTechWcfService 
    { 
     [OperationContract] 
     List<Customer> GetCustomers(); 



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

namespace YeagerTechModel 
{ 
    [Serializable] 
    [DataContract] 
    public partial class Customer 
    { 
     public Customer() 
     { 
      this.Projects = new HashSet<Project>(); 
     } 

     [DataMember] 
     public short CustomerID { get; set; } 

     [Required] 
     [StringLength(50)] 
     [DataType(DataType.EmailAddress)] 
     [DataMember] 
     public string Email { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string Company { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string FirstName { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string LastName { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string Address1 { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string Address2 { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string City { get; set; } 

     [StringLength(2)] 
     [DataType(DataType.Text)] 
     [DataMember] 
     public string State { get; set; } 

     [StringLength(10)] 
     [DataType(DataType.Text)] 
     [RegularExpression(@"^\d{5}(-\d{4})?$")] 
     [DataMember] 
     public string Zip { get; set; } 

     [StringLength(12)] 
     [DataType(DataType.PhoneNumber)] 
     public string HomePhone { get; set; } 

     [StringLength(12)] 
     [DataType(DataType.PhoneNumber)] 
     [DataMember] 
     public string CellPhone { get; set; } 

     [StringLength(100)] 
     [DataType(DataType.Url)] 
     [DataMember] 
     public string Website { get; set; } 

     [StringLength(50)] 
     [DataType(DataType.EmailAddress)] 
     [DataMember] 
     public string IMAddress { get; set; } 

     [DataMember] 
     public System.DateTime CreatedDate { get; set; } 

     [DataMember] 
     public Nullable<System.DateTime> UpdatedDate { get; set; } 

     public virtual ICollection<Project> Projects { get; set; } 
    } 


public List<Customer> GetCustomers() 
     { 
      YeagerTechEntities DbContext = new YeagerTechEntities(); 

      List<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0).ToList(); 

      return customer.ToList(); 
     } 
+1

Avez-vous regardé dans le journal des événements Windows sur la machine sur laquelle le service est en cours d'exécution? Avez-vous essayé de déboguer le service? Avez-vous essayé simplement de retourner 'new List (new [] {new Priority()});'? –

+0

Essayez de vérifier le service pour les exceptions, pas seulement le client –

+0

J'ai activé le suivi et ai eu une erreur plus descriptive msg. Je vais modifier mon post original pour l'inclure. S'il vous plaît vérifier et laissez-moi savoir .... – sagesky36

Répondre

7

La réponse était aussi simple que définir une propriété à faux avant de faire mon appel EF la base de données. DbContext.Configuration.ProxyCreationEnabled = false; EF génère automatiquement une classe proxy. Proxies dynamiques - Ils ne jouent pas bien sur le fil - Désactivez-les (ContextOptions.ProxyCreationEnabled == false).

+0

Eh bien, gee, cette réponse est un peu décevante si vous vouliez utiliser les proxies aussi. – Casey

Questions connexes