在ASP.NET WebService中接受UTF-8编码的字符串

4
我有一个类似于这样的ASP.NET WebService:
[WebMethod]
public static void DoSomethingWithStrings(string stringA, string stringB)
{
    // and so on
}

一个第三方应用程序应该调用这个Web服务。然而,这个应用程序将字符串编码为UTF-8,并且所有的umlauts都被替换为“??”。我可以查看调用和特殊字符的格式化很好:
<?xml version="1.0" encoding="utf-8" ?>
<!-- ... -->
<SoapCall>
    <DoSomethingWithStrings>
        <stringA>Ä - Ö - Ü</stringA>
        <stringB>This is a test</stringB>
    </DoSomethingWithStrings>
</SoapCall>

当我在webservice方法中简单打印字符串时,会产生以下输出:

?? - ?? - ??

这是一个测试

如何配置WebService接受UTF-8编码的字符串?

更新

Fiddler还告诉我,http请求的内容类型字符集为UTF-8。

更新2

我尝试添加以下代码到global.asax进行调试:

public void Application_BeginRequest(object sender, EventArgs e)
{
    using (var reader = new System.IO.StreamReader(Request.InputStream))
    {
        string str = reader.ReadToEnd();
    }
}

这里读取了实际的SOAP调用。 StreamReader 的编码设置为UTF-8。 SOAP调用看起来是正确的:

<?xml version="1.0" encoding="UTF-8" ?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <DoSomethingWithStrings xmlns="http://www.tempuri.org/">
            <stringA>Ä - Ö - Ü</stringA>
            <stringB>This is a test!</stringB>
        </DoSomethingWithStrings>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

web.config文件中,全球化设置已正确设置:
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" culture="de-DE" uiCulture="de-DE" />

所以看起来某个反序列化SOAP消息的东西没有使用UTF-8而是ASCII编码。

只是一个技术上的细节,但“encrypted”一词并不准确。由于UTF-8仅仅是个字符集,因此使用“encoded(编码)”会更为准确。 - Tomas McGuinness
当然,你是正确的,对于这个混淆我很抱歉 :) - Carsten
4个回答

6
最终发现在接受HTTP消息时出了问题。我不知道是什么操纵了HTTP请求,但我找到了一个解决方法。虽然 Fiddler 在我的 Application_BeginRequest 中显示了正确的内容类型(text/xml; charset=utf-8),但 Request.RequestContext.HttpContext.Request.ContentType 只是 text/xml,这导致 ASMX 序列化器回退到默认(ASCII)编码。我已经将以下代码添加到 Application_BeginRequest 处理程序中,目前一切都正常运行。
if (Request.RequestContext.HttpContext.Request.ContentType.Equals("text/xml"))
{
    Request.RequestContext.HttpContext.Request.ContentType = "text/xml; charset=UTF-8";
}

感谢您的帮助!

很高兴听到你已经解决了它,不过我想知道为什么它没有回退到从xml中读取编码属性。我很确定任何自动化的过程都应该能够正确处理它,因为所有信息都在那里,只有手动覆盖才会出错。 - Esailija
正是这个原因,我才问这个问题...我不知道为什么 SOAP 消息(通常是 XML 消息)不能像 XML 文件一样解析。无论如何...感谢您的帮助 :-) - Carsten
使用自定义 SoapExtension 也做了同样的事情。在 ProcessMessage 方法中,在反序列化之前添加了 "charset=UTF-8" - urbanSoft

0

试试这个:

  byte[] bytes=Encoding.UTF8.GetBytes(yourString);

注意:

字符串永远不会包含任何utf-*或其他编码


字符串(或System.Strings)是一组Unicode字符(http://msdn.microsoft.com/en-us/library/system.string.aspx)。也许我可以通过这种方式从UTF-8编码的字符串中获取字节,但在该字符串内部,变音符已经被替换。我已更新问题。 - Carsten

0

SOAP调用在某个地方被解码为ASCII - 每个umlaut都是2个字节,高位被设置,这会在解码为ASCII时变成??

因此,类似以下情况正在发生:

byte[] bytesSentFromClient = Encoding.UTF8.GetBytes("Ä - Ö - Ü");
string theStringIThenReceiveInMyMethod = Encoding.ASCII.GetString(bytesSentFromClient);
Console.WriteLine(theStringIThenReceiveInMyMethod);
//?? - ?? - ??

为了确保这一点,您应该比较 stringA == "Ä - Ö - Ü" 而不是在某个地方打印它。
我猜您可以通过全局搜索“ASCII”来开始,然后如果找到任何内容,就从那里开始工作。
您也可以尝试
<globalization requestEncoding="utf-8" responseEncoding="utf-8"/>

在 Web.config 文件中的 标签下。

有趣的观点!感谢您的研究。我尝试解码请求输入流并更新了问题(更新2)。同时,在整个解决方案中搜索ASCII也没有找到任何匹配项。 - Carsten

0

我曾经遇到过同样的问题。Asmx Web服务将我的UTF-8转换成了ASCII,或者更准确地说是??????。你的帖子对我帮助很大。 我找到的解决方案是将SOAP协议版本从1.1改为1.2 我的意思是:

POST /WebService1.asmx HTTP/1.1
Host: www.tempuri.org
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.tempuri.org/HelloWorld"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <HelloWorld xmlns="http://www.tempuri.org/">
        <inputParam>Привет</inputParam>
    </HelloWorld>
  </soap:Body>
</soap:Envelope>

我遇到了问题。但是当我将请求更改为SOAP 1.2时:

POST /WebService1.asmx HTTP/1.1
Host: www.tempuri.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <HelloWorld xmlns="http://www.tempuri.org/">
       <inputParam>Привет</inputParam>
    </HelloWorld>
  </soap12:Body>
</soap12:Envelope>

问题已经解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接