引发异常时,ASP.NET WebService返回乱码
我有一个Web服务(ASMX),其中有一个Web方法,该方法可以完成一些工作,如果输入无效,则会引发异常。
[ScriptMethod] [WebMethod] public string MyWebMethod(string input) { string l_returnVal; if (!ValidInput(input)) { string l_errMsg = System.Web.HttpUtility.HtmlEncode(GetErrorMessage()); throw new Exception(l_errMsg); } // some work gets done... return System.Web.HttpUtility.HtmlEncode(l_returnVal); }
回到网页上的客户端JavaScript,在错误回调函数上,我显示我的错误:
function GetInputErrorCallback(error) { $get('input_error_msg_div').innerHTML = error.get_message(); }
这很好用,当我的Web方法返回(字符串)时,它总是看起来很完美。但是,如果我抛出的异常中的错误消息之一包含特殊字符,则该错误消息将在浏览器中错误显示。例如,如果错误消息包含以下内容:
该输入无效! (那里是ASCII#146)
它显示如下:
该输入信息无效!
或者:
你喜欢Hsker D吗? (ASCII 252)
成为:
你喜欢H ?? sker D ???吗?
错误消息的内容来自具有UTF-8编码的XML文件:
<?xml version="1.0" encoding="UTF-8"?> <ErrorMessages> <Message id="invalid_input">Your input isn’t valid!</Message> . . . </ErrorMessages>
就页面编码而言,在我的Web.config中,我有:
<globalization enableClientBasedCulture="true" fileEncoding="utf-8" />
我也有一个HTTP模块来设置L10n参数:
Thread.CurrentThread.CurrentUICulture = m_selectedCulture; Encoding l_Enc = Encoding.GetEncoding(m_selectedCulture.TextInfo.ANSICodePage); HttpContext.Current.Response.ContentEncoding = l_Enc; HttpContext.Current.Request.ContentEncoding = l_Enc;
我尝试禁用此HTTP模块,但结果是相同的。
Web服务返回的值(在l_errMsg变量中)在VS调试器中看起来不错。一旦客户端脚本保留了,它就显示不正确。我已经使用Firebug来查看响应,并且在那里也改写了特殊字符。因此,我感到奇怪的是,即使其中包含特殊字符,我的Web方法返回的字符串也看起来不错。但是,当我从Web方法引发异常时,其消息中的特殊字符是不正确的。我怎样才能解决这个问题?
解决方案
回答
确定要设置" fileEncoding"而不是" responseEncoding"吗?设置fileEncoding决定了Web服务器在无法自动确定编码时如何尝试从磁盘读取物理.asmx / .aspx文件。因此,将此设置为" utf-8"意味着我们必须将所有.asmx / .aspx文件保存在utf-8中。我不认为是相关的。
我们所看到的重击是使用8位编码来解析编码为utf-8的文本(即,使用8位解码器对utf-8字节流进行解码,例如iso-8859-1 / Windows-1252)。因此,在throw()引发Exception之前正在执行的HtmlEncode()可能与预期的输出编码有误。那么,如果我们没有HtmlEncode()错误消息怎么办?
(从技术上讲," ASCII 252"不太正确; ASCII有128个字符;我们使用的撇号来自8位编码,例如iso-8859-1 / Windows-1252. )
我们确定已正确禁用该HTTP模块吗?此行看起来可能是引起问题的原因:
HttpContext.Current.Response.ContentEncoding = l_Enc;
...因为最有可能将输出编码设置为8位编码(相当于ANSI代码页)。
为了支持尽可能多的文化,我们应该将响应编码设置为utf-8. 这是浏览器中最受支持的Unicode格式(我敢说所有现代浏览器都支持它),并且Unicode是本地编码的唯一替代方法。就是说,我不完全了解我们正在使用什么HTTP模块以及为什么需要它,因此情况可能比我想的要复杂。