我将带有WCF接口的现有ASMX Web服务包装为我的软件项目中的过渡阶段,以节省时间。除了一个返回System.String的函数之外,这很有效。
原始ASMX服务根据给定的参数返回文本或XML。这在ASMX中不是问题。在WCF中,返回的值(如果是XML)被转义为:<gml>
,它应该是<gml>
。请参阅SOAP下面的内容。
请求
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>
响应
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><gml>data</gml></FunctionResult>
</FunctionResponse>
</s:Body>
</s:Envelope>
一些谷歌搜索让我返回一个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);
这很有用。
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};
然而,SOAP消息中返回的结果是:
MDIwMTA0MTVEQkQ4MDBEN0UxNzU3Nzc4N0E2MjY5Nzg=
因此产生的输出是乱码(我认为,再次由消息编码(?)引起)
该方法是带有OperationContract的attr,并且该服务在IIS6中托管,具有以下ABC:
<service name="WebServices.BeheerUtils" behaviorConfiguration="Services.ServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="WebServices.IUtils"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
为什么输出会出现乱码或者如何阻止HTML编码?
接口
[OperationContract]
System.IO.Stream Function(string type, string input1, string input2, string input3);
实施
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 :(得分:1)
我不同意这句话:
这在ASMX中不是问题。在WCF中,返回值(如果是XML)是 像
<gml>
一样转义,应该是<gml>
。
我用方法创建了一个服务:
[OperationContract]
string GetXml(string str);
public string GetXml(string str)
{
return "<gml>" + str + "</gml>";
}
然后我用生成的WCF客户端调用该服务:
var client = new MyWcfServiceClient();
var result = client.GetXml("test");
结果是:
<gml>test</gml>
<强>更新强>
为了确保它是xml行为的标准方式,请执行以下测试并检查respone.FunctionResult
的值:
public class FunctionResponse
{
public string FunctionResult { get; set; }
}
public void Test()
{
var serialized = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<FunctionResponse>
<FunctionResult><gml>data</gml></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);
}
}
}
答案 1 :(得分:1)
如果你的函数返回一个字符串,那么它应该被编码是正常的。
您可以尝试声明函数返回XmlNode
而不是字符串。
答案 2 :(得分:0)
使用basicHttpBinding而不是wsHttpBinding。
答案 3 :(得分:0)
所以我摆弄了一些返回类型,这就是我能做到的:
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;
我基本上将所有响应都包装在一个新的Root元素中。这给了我SOAP封装的文字XML而不是'html encoded'。虽然它能满足我的需求,但我发现它很尴尬。然而,我发现没有其他解决方案符合我的需要,因此我将其作为最终解决方案。