2012-05-04 4 views
0

J'enveloppe un service Web ASMX existant avec une interface WCF en tant que phase de transition dans mon projet logiciel pour gagner du temps. Cela fonctionne bien, sauf pour une fonction qui renvoie un System.String.WCF a renvoyé System.IO.Stream brouillé

Le service ASMX original renvoyait du texte ou du code XML en fonction des paramètres donnés. Ce n'était pas un problème dans ASMX. Dans WCF, la valeur renvoyée, si XML, est échappée comme suit: &lt;gml&gt; où elle doit être <gml>. S'il vous plaît voir le SOAP ci-dessous.

Demande

POST http://someuri.org/WebServices/Utils.svc HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
SOAPAction: http://www.someuri.org/IUtils/Function 
Content-Length: 283 
Accept: */* 
User-Agent: Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5) 
Host: foo.bar.org 
Connection: Keep-Alive 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Body> 
     <Function xmlns="http://www.someri.org/"> 
      <type>...</type> 
      <input1>...</input1> 
      <input2>...</input2> 
      <input3>true</input3> 
     </Function > 
    </s:Body> 
</s:Envelope> 

Réponse

HTTP/1.1 200 OK 
Date: Fri, 04 May 2012 11:40:01 GMT 
Server: Microsoft-IIS/6.0 
X-Powered-By: ASP.NET 
X-AspNet-Version: 2.0.50727 
Cache-Control: private 
Content-Type: text/xml; charset=utf-8 
Content-Length: 2070 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Body> 
     <FunctionResponse xmlns="http://www.crotec.nl/"> 
      <FunctionResult>&lt;gml&gt;data&lt;/gml&gt;</FunctionResult> 
     </FunctionResponse> 
    </s:Body> 
</s:Envelope> 

googling m'a amené à retourner un objet System.IO.Stream.

string result = DoStuff(arg1, arg2, arg3);    
byte[] bin = Encoding.UTF8.GetBytes(result); 
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"; 
return new System.IO.MemoryStream(bin); 

Cela fonctionne dans une certaine mesure.

string result = "02010415DBD800D7E17577787A626978"; 
byte[] bin = {48,50,48,49,48,52,49,53,68,66,68,56,48,48,68,55,69,49,55,53,55,55,55,56,55,65,54,50,54,57,55,56}; 

Le résultat retourné dans le message SOAP est cependant:

MDIwMTA0MTVEQkQ4MDBEN0UxNzU3Nzc4N0E2MjY5Nzg= 

Ainsi, la sortie résultante est brouillée (? Encore, je pense, causé par le codage des messages())

Le méthode est attr avec un de OperationContract et le service est hébergé dans IIS6 avec l'ABC suivante:

<service name="WebServices.BeheerUtils" behaviorConfiguration="Services.ServiceBehavior"> 
    <!-- Service Endpoints --> 
    <endpoint address="" binding="basicHttpBinding" contract="WebServices.IUtils"/> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
</service> 

Des idées pour lesquelles la sortie est brouillée ou comment empêcher l'encodage HTML?

Interface

[OperationContract] 
System.IO.Stream Function(string type, string input1, string input2, string input3); 

mise en œuvre

public new System.IO.Stream Function(string type, string input1, string input2, string input3) 
{ 
    // Call the old ASMX method 
    string result = DoStuff(type, input1, input2, input3, true); 

    byte[] bin = Encoding.UTF8.GetBytes(result); 
    WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"; 
    return new System.IO.MemoryStream(bin); 
} 
+0

Le texte 'MDIwMTA0MTVEQkQ4MDBEN0UxNzU3Nzc4N0E2MjY5Nzg =' est la valeur encodée en base64 de '02010415DBD800D7E17577787A626978'. – empi

+0

Pourriez-vous publier des détails sur votre interface de service WCF - au moins la définition de la méthode. Je ne comprends pas vraiment pourquoi en utilisant asmx vous pouvez retourner une chaîne ou xml et en utilisant WCF vous ne pouvez pas le faire (n'est pas xml juste une chaîne?). – empi

+0

Merci pour la mise à jour, mais pourriez-vous répondre à ma deuxième question - pourquoi ne pouvez-vous pas simplement renvoyer la chaîne? – empi

Répondre

0

Je bidouillé autour de certains types de retour et c'est ce que je peux avec:

string result = DoStuff(type, input1, input2, input3, true); 

XDocument d = new XDocument(); 
XDocument basis = new XDocument(new XElement("result")); 

// Load the result into a XDocument, add the result as a value of the wrapper element if the format is invalid  
try 
{ 
    d = XDocument.Parse(result); 
    basis.Root.Add(d.Root); 
} 
catch (Exception) 
{ 
    basis.Root.Value = result; 
}  

// Return the XElement 
return basis.Root; 

J'enveloppe essentiellement toutes les réponses dans un nouvel élément racine. Cela me donne du XML littéral dans le SOAP enveloppé au lieu de 'html encoded'. Bien qu'il fasse ce dont j'ai besoin, je trouve ça bizarre. Cependant, je n'ai trouvé aucune autre solution répondant à mes besoins et je présente ceci comme la solution finale.

0

Utilisation basicHttpBinding au lieu de wsHttpBinding.

+0

Je suis ;-) (voir la question mise à jour) – Nebula

1

Je ne peux pas d'accord avec cette affirmation:

Ce ne fut pas un problème dans ASMX. Dans WCF, la valeur renvoyée, si XML, est s'est échappée comme suit: &lt;gml&gt; où elle doit être <gml>.

J'ai créé un service avec la méthode:

[OperationContract] 
string GetXml(string str); 

public string GetXml(string str) 
{ 
    return "<gml>" + str + "</gml>"; 
} 

Et puis j'appeler le service avec le client WCF généré:

var client = new MyWcfServiceClient(); 
var result = client.GetXml("test"); 

Le résultat est:

<gml>test</gml> 

MISE À JOUR

Juste pour vous assurer qu'il est un moyen standard pour XML à se comporter s'il vous plaît effectuer le test suivant et vérifiez la valeur de respone.FunctionResult:

public class FunctionResponse 
{ 
    public string FunctionResult { get; set; } 
} 

public void Test() 
{ 
    var serialized = @"<?xml version=""1.0"" encoding=""UTF-8""?> 
<FunctionResponse> 
    <FunctionResult>&lt;gml&gt;data&lt;/gml&gt;</FunctionResult> 
</FunctionResponse>"; 
    var ser = new XmlSerializer(typeof(FunctionResponse)); 
    using (var stringReader = new StringReader(serialized)) 
    { 
     using (var xmlReader = new XmlTextReader(stringReader)) 
     { 
      var response = ser.Deserialize(xmlReader);      
     } 
    }    
} 
+0

Je vous assure, je ne mens pas. S'il vous plaît voir la question mise à jour. – Nebula

+0

@Nebula: Je ne dis pas que vous mentez :) Je dis que si vous générez/créez le client wcf, vous devriez obtenir un résultat correct. – empi

+0

Ah, maintenant je vois le problème. En fait, le service est consommé par un site Web ASP classique.Je suppose que c'est là qu'un écart existe. Nous devons écrire tous les messages à la main afin qu'il n'y ait pas de cadre que je puisse utiliser. – Nebula

1

Si votre fonction retourne une chaîne, alors il est normal qu'il devrait être encodé.

Vous pouvez essayer de déclarer votre fonction pour renvoyer un XmlNode au lieu d'une chaîne.

+0

Un XmlNode pourrait-il contenir du texte brut comme weel? Donc, sans élément parent? – Nebula

+0

Ajout à ma première réponse; Je ne pense pas nécessairement que ce soit normal qu'il soit évité. Au moins pas sans me donner une option pour désactiver cette fuite. Peut-être qu'il existe une telle option? Dans ce cas, je voudrais apprendre comment faire cela car je suis incapable d'obtenir cela pour le moment. – Nebula

+0

@Nebula, je ne connais pas d'option pour désactiver l'échappement. Une chaîne à l'intérieur d'un message SOAP doit être échappée, mais cela doit être transparent pour l'appelant - toute API XML qui extrait le contenu du noeud désapparaîtra automatiquement la chaîne. – Joe

Questions connexes