Comment puis-je diffuser une réponse de WCF sans mise en mémoire tampon?

J’ai un service WCF auto-hébergé reposant (webHttpBinding). La plupart des méthodes renvoient la version xml ou json des objects au client.

J’ai quelques méthodes GET qui déclenchent des méthodes d’exécution longues et j’aimerais diffuser le journal en réponse dans le navigateur (ou l’application) afin que l’utilisateur sache ce qui se passe. Ce serait simple à accomplir avec HttpContext.Current.Response.OutputStream.Write . Malheureusement, HttpContext.Current est toujours nul dans un service WCF auto-hébergé, même si aspNetCompatibilityEnabled configuration aspNetCompatibilityEnabled (IIS n’est malheureusement pas une option).

J’ai essayé AnonymousPipeServerStream : WCF et requêtes et réponses en continu

avec le premier réglage:

 OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse; context.ContentType = "text/plain"; 

de sorte que la réponse parvienne au navigateur, il ne télécharge pas le stream dans un fichier à enregistrer.

Sous Chrome, cela ne fonctionne pas du tout: il tamponne jusqu’à la fin. Dans IE ou wget, il semble tamponner pour environ 4k (ou quelque chose) à la fois. Ce n’est pas bon pour la journalisation car à moins que je ne crache des charges inutiles de journaux pour forcer la sortie, l’utilisateur ne sait pas vraiment ce qui se passe. Je peux seulement supposer que c’est parce que la réponse est en fait une réponse en bloc et que les morceaux sont en 4k (plutôt que d’écrire dans le stream de sortie).

Le correctif pour obtenir la sortie de chrome est apparemment d’écrire des ordures dans le contenu avant d’envoyer la réponse en bloc : Encodage de transfert en bloc – comportement du navigateur , cependant, je ne pense pas que cela soit possible avec WCF.

Donc, les solutions possibles que je cherche:

  • Un moyen d’écrire dans le stream de sortie dans WCF dans un service auto-hébergé (sans IIS). ou
  • Un moyen de contrôler la taille des blocs dans une réponse de stream (et un moyen d’écrire d’abord du contenu afin que Chrome rende les morceaux).

Une autre option, je suppose, est d’abandonner la WCF au profit de quelque chose de plus convivial (je commence à penser que la WCF n’était pas le bon choix). Cependant, après avoir tant écrit dans la WCF, cela semble être une tâche fastidieuse. À moins que quelque chose me permette de basculer vers cela, la migration serait facile (par exemple, si je pouvais réutiliser les mêmes classes de service, peut-être avec juste des atsortingbuts différents). Nancy peut-être?

J’ai fait quelque chose comme ce que vous demandez ici – auto-hébergé aussi. J’ai écrit un service WCF (BasicHttpBinding) qui effectuait à la fois la diffusion en continu et la mise en mémoire tampon des données sur les périphériques clients utilisant mon service pour la synchronisation des données. Le streaming est difficile, comme vous l’avez probablement compris, et je ne pense pas qu’il y ait un moyen “d’écrire dans le stream”.

De manière générale, la diffusion en continu sur un service WCF fonctionne de la même manière que File.IO, comme le montre le code ci-dessous.

  FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs); 

Si le fichier en question est de 1 Go, votre stream de fichiers commencera à renvoyer des octets avant sa lecture à la fin du fichier. Le streaming sur WCF fonctionne de la même manière (en fait, il implémente FileStream, selon mon expérience), c’est pourquoi il est bon pour les énormes quantités de données. Ça se lit … ça envoie; ça se lit … ça envoie. Donc, je ne sais pas comment vous allez injecter des informations dans ce stream pour les afficher sur votre écran.

Cela dit, notre interface utilisateur Synch affiche le nombre d’octets à descendre, ainsi que le pourcentage de complétion, pour empêcher les utilisateurs d’éteindre la machine ou de les annuler. Pour ce faire, un thread séparé lit la taille du fichier à télécharger toutes les 10 secondes et calcule le pourcentage du tout (la taille complète est renvoyée en tant que paramètre dans la réponse), puis en écrivant les résultats dans la fenêtre de résultats de l’interface utilisateur. . Donc, la solution est en fait assez simple, dans notre cas.

Je fais le streaming de fichiers comme ceci:

Regroupez les méthodes qui renvoient des données devant être diffusées en continu sur un noeud final, puis ajoutez le transferMode transmis en continu sur ce noeud final.

Voici la configuration que j’utilise (pour basicHttpBinding).

      

et définissez la configuration de la liaison:

      

Fondamentalement, vous devez définir le transferMode dans la configuration de la liaison.

Je ne l’ai pas essayé avec webHttpBinding, alors faites-le-moi savoir si cela fonctionne pour vous.

Il suffit de faire croire au navigateur qu’il existe une réponse HTML avec le type de Multipart Content-Type

http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

Je l’ai utilisé pour un certain nombre de choses, y compris MJPEG, mais vous pouvez également l’utiliser pour les réponses COMET / WebSocket.