引发异常时,ASP.NET WebService返回乱码

时间:2020-03-05 18:53:30  来源:igfitidea点击:

我有一个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模块以及为什么需要它,因此情况可能比我想的要复杂。