Mélange de XML et de JSON dans RESTful WCF sans méthodes séparées

J’ai un service RESTful WCF qui peut renvoyer XML, JSON ou JSONP, en fonction des arguments, par exemple /service.svc/stuff?format=xml ou service.svc/stuff?format=json&callback=myCallback . Pour ce faire, j’ai créé Behavior, MethodEncoder et MethodEncoderFactory personnalisés, qui traitent le rappel au format JSONP et choisissent le rédacteur en fonction de l’argument de format. Dans la méthode WriteMessage() mon encodeur, je fais quelque chose comme:

 XmlWriter writer = IsXmlRequested() ? XmlDictionaryWriter.CreateTextWriter(stream) : JsonReaderWriterFactory.CreateJsonWriter(stream) message.WriteMessage(writer); 

Ensuite, je définis mes méthodes de service comme si elles venaient de renvoyer du JSON mais utilisaient mon élément de liaison personnalisé:

 [OperationContract, JSONPBehavior, WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "stuff") public List GetStuff(){...} 

Et ça marche presque. Lorsque je demande XML ou JSON, j’obtiens quelque chose dans le bon format, mais le XML n’est pas sérialisé comme je le souhaite. Voici à quoi ressemble le XML:

   1 

Alors que si je définissais simplement WebMessageFormat sur XML, j’obtiendrais quelque chose comme ceci:

   1 

Je veux vraiment le dernier. Je suppose que cela se produit car le résultat est sérialisé dans un dictionnaire lors de la création de l’object Message; mon encodeur personnalisé est en train de décider comment écrire ce dictionnaire dans le stream de réponses. Donc, le codage est correct, mais pas exactement le format, qui a déjà été décidé par ResponseFormat.

D’abord, est-ce vrai? Si oui, comment puis-je résoudre ce problème? Par exemple, puis-je écrire mon propre WebMessageFormat? Ou dois-je simplement donner et écrire des méthodes séparées (et des modèles d’URI) ayant des propriétés ResponseFormat différentes pour / json / * et / xml / *?

Mise à jour: dans .net 4, il existe une propriété WebOperationContext.Current.OutgoingResponse.Format vous pouvez simplement définir. Je suppose que mon problème se résume à ceci: existe-t-il un moyen de réaliser cela dans .net 3.5?

Oui, il existe un moyen d’accomplir ce que vous voulez dans .NET 3.5, sans écrire de méthodes séparées.

Cet article de blog traite de la situation que vous décrivez: modifier le type de contenu de la réponse en fonction de la demande entrante. Mais, l’article décrit une approche légèrement différente de la solution.

En particulier, le demandeur spécifie le type de contenu souhaité PAS dans l’URL de la demande, mais plutôt dans l’en-tête Accept de la demande.

La solution implique l’utilisation d’un WebHttpBehavior personnalisé qui inspecte l’en-tête Accept et formate la réponse de manière appropriée. Une solution très élégante, à mon avis. Dans votre logique métier, vous n’avez rien à faire pour obtenir le formatage adaptatif. Attachez simplement le comportement et ça marche.


Consultez également la bibliothèque WCF REST Consortingb sur CodePlex.