2009-09-07 10 views
4

J'ai des problèmes avec un service WCF. Le type de retour est un type semi-complexe qui fait référence à divers types de base et à une interface de base dont chacun de ces types hérite.Comment résoudre cette exception WCF?

Dans mon débogage, la taille totale des octets du message sérialisé est bien inférieure au seuil par défaut de 65535 octets. Néanmoins, j'ai augmenté l'attribut maxReceivedMessageSize à 1000000 et le problème persiste.

Le service WCF est défini comme suit:

[ServiceContract] 
public interface ILoggingService 
{ 
    [OperationContract] 
    NotesInfo ListNotes(NotesQueryOptions options); 
} 

Voici la définition de l'objet de retour NotesInfo:

[DataContract] 
public class NotesInfo 
{ 
    [DataMember] public List<TokenizedNote> Notes { get; set; } 
    [DataMember] public Dictionary<long, User> Users { get; set; } 
    [DataMember] public Dictionary<long, NoteCategory> NoteCategories { get; set; } 
    [DataMember] public Dictionary<string, Dictionary<long, IIdentifiable<long>>> EntitiesByToken { get; set; } 
} 

Lorsque je tente d'appeler le service, je obtenir l'exception suivante levée:

The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.

Source Error:

Line 242: 
Line 243: public AxeFrog.Mobile.NotesInfo ListNotes(AxeFrog.Mobile.NotesQueryOptions options) { 
Line 244:   return base.Channel.ListNotes(options); 
Line 245:  } 
Line 246: } 

Source File: C:\Users\Nathan\Work\Internal Projects\AxeFrog System\Source\Trunk\AxeFrog.Mobile.WebInterface\Service References\LoggingServiceReference\Reference.cs Line: 244

est Ci-dessous le code pour les autres entités impliquées:

public interface IIdentifiable<TID> 
{ 
    TID ID { get; set; } 
} 

[DataContract] 
public class Note : IIdentifiable<long> 
{ 
    [DataMember] public long ID { get; set; } 
    [DataMember] public DateTime DateStamp { get; set; } 
    [DataMember] public long? UserID { get; set; } 
    [DataMember] public long NoteCategoryID { get; set; } 
    [DataMember] public NoteType NoteType { get; set; } 
    [DataMember] public string Message { get; set; } 
} 

public enum NoteType 
{ 
    Information = 0, 
    Warning = 10, 
    Failure = 20 
} 

[DataContract] 
public class NoteCategory : IIdentifiable<long> 
{ 
    [DataMember] public long ID { get; set; } 
    [DataMember] public string Name { get; set; } 
} 

[DataContract] 
public class NoteEntityType : IIdentifiable<long> 
{ 
    [DataMember] public long ID { get; set; } 
    [DataMember] public Type TypeName { get; set; } 
} 

[DataContract] 
public class TokenizedNote 
{ 
    [DataMember] public Note Note { get; set; } 
    [DataMember] public List<NoteSegment> NoteSegments { get; set; } 
} 

public abstract class NoteSegment 
{ 
    public abstract string Render(INoteRenderer renderer, Dictionary<string, Dictionary<long, IIdentifiable<long>>> entitiesByToken); 
} 

[DataContract] 
public class NoteTextSegment : NoteSegment 
{ 
    [DataMember] 
    public string Text { get; set; } 
} 

[DataContract] 
public class NoteEntitySegment : NoteSegment 
{ 
    [DataMember] public long EntityID { get; set; } 
    [DataMember] public string Token { get; set; } 
} 

Notez que j'ai supprimé le Render() remplace des implémentations abstraites de NoteSegment par souci de lisibilité .

Voici quelques informations de thedebugger afin que vous puissiez voir ce qui est retourné:

alt text alt text

Toute idée de ce que je pourrais faire mal ici serait apprécié. Une recherche Google donne peu de réponses utiles.

+0

est-ce un LAN d'entreprise derrière un pare-feu? Dans ce cas, je recommande la liaison NetTcp - beaucoup plus rapide et plus efficace que le standard, plutôt lourd wsHttpBinding ... –

+0

mais netTcp a besoin de IIS7 (Win Server 2008 ou supérieur ou Vista) ou auto-hébergement –

+0

Non, tout est sur localhost à ce stade. –

Répondre

0

Vous affichez une exception sur le client; que se passe-t-il lorsque vous attachez un débogueur sur le serveur (ou activez la journalisation), voyez-vous quelque chose d'utile?

+0

Il n'y a pas d'erreur côté serveur. Il construit et retourne avec succès l'objet de retour. –

+0

Hm. Un serveur et un client aléatoires ont des contrats incompatibles (par exemple, le contrat de serveur a été modifié, mais pas le client)? Peut-être besoin d'utiliser par ex. Fiddler pour voir ce qui se passe sur le fil. – Brian

+0

Non, j'ai effectué une mise à jour sur la référence du service juste pour vérifier. –

0

Cela peut être dû à un message trop long. Vous devriez essayer de changer les limites en éditant votre app.config comme ceci:

<binding name="WebBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> 
    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
    maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
+0

Merci pour la réponse. La troisième phrase du premier paragraphe de la question se lit comme suit: "Dans mon débogage, la taille totale des octets du message sérialisé est bien inférieure au seuil par défaut de 65535 octets." –

+0

@Nathan: la longueur du message n'est pas le seul seuil significatif. À savoir, vérifiez le paramètre maxArrayLength – Brann

+0

Avoir essayé cela aussi, bravo. Toujours avoir l'erreur cependant. –

0

pourrait-il que votre serveur prend juste un peu trop de temps pour mettre en place la réponse? La valeur par défaut « sendTimeout » sur le client est seulement 60 secondes - vous pouvez essayer d'augmenter ce à quelque chose de plus:

<binding name="TweakedBinding" sendTimeout="120" /> 

À quoi ressemble votre config client comme? Quelle liaison utilisez-vous? Quels paramètres de sécurité?

Marc

MISE À JOUR:
pouvez-vous ajouter le comportement de débogage de service à votre service, de sorte que vous obtiendrez plus d'informations et de débogage erreur sur la fin du client quand quelque chose va mal ??

<behaviors> 
    <serviceBehavior> 
    <behavior name="YourBehaviorName"> 
     <serviceDebug includeExceptionDetailInFaults="True" /> 
    </behavior> 
    </serviceBehavior> 
</behaviors> 
+0

Non, la réponse est très rapide. Je viens de mettre à jour la question pour montrer une capture d'écran de l'information du débogueur. –

+0

La configuration de liaison et de sécurité sont toutes des valeurs par défaut générées par Visual Studio. Le service est via ASP.Net et configuré pour fonctionner via IIS plutôt que le serveur Web intégré. –

0

Cette question est ancienne, mais je la jetterai au cas où quelqu'un d'autre la trouverait utile. Je devine l'héritage de NoteSegment - vous devrez utiliser l'attribut KnownType pour indiquer à l'objet TokenizedNote qu'il peut attendre NoteTextSegment et NoteEntitySegment quand il désérialise (puisque par défaut il attendrait seulement une instance de NoteSegment).

[DataContract] 
[KnownType(typeof(NoteEntitySegment)] 
[KnownType(typeof(NoteTextSegment)] 
public class TokenizedNote 
{ 
    [DataMember] public Note Note { get; set; } 
    [DataMember] public List<NoteSegment> NoteSegments { get; set; } 
} 

Voir cette ressource pour plus de détails: http://msdn.microsoft.com/en-us/library/ms730167(v=vs.110).aspx

0

J'avais un problème similaire. Après avoir réfléchi pendant 2 heures et essayé de trouver une réponse en ligne, j'ai décidé de suivre l'approche pour sérialiser et désérialiser la valeur de retour/objet du côté serveur en utilisant le System.Runtime.Serialization.DataContractSerializer et finalement trouvé que avait manqué d'ajouter l'attribut EnumMember sur l'un des Enums.

Voici l'extrait de code qui m'a aidé à résoudre le problème:

 var dataContractSerializer = new System.Runtime.Serialization.DataContractSerializer(typeof(MyObject)); 
     byte[] serializedBytes; 
     using (System.IO.MemoryStream mem1 = new System.IO.MemoryStream()) 
     { 
      dataContractSerializer.WriteObject(mem1, results); 
      serializedBytes = mem1.ToArray(); 
     } 

     MyObject deserializedResult; 
     using (System.IO.MemoryStream mem2 = new System.IO.MemoryStream(serializedBytes)) 
     { 
      deserializedResult = (MyObject)dataContractSerializer.ReadObject(mem2); 
     } 
0

Ouvrez IIS, sélectionnez le site, cliquez sur "Paramètres de base", puis cliquez sur "Paramètres de test". Ce que j'avais oublié, c'est que le site a besoin d'informations d'identification valides ainsi que de son pool d'applications.

Questions connexes