ASP.NET WebService Returns Gibberish Characters When Throwing Exceptions
-
09-06-2019 - |
Question
I have a web service (ASMX) and in it, a web method that does some work and throws an exception if the input wasn't valid.
[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);
}
Back in the client-side JavaScript on the Web page, on the error callback function, I display my error:
function GetInputErrorCallback(error)
{
$get('input_error_msg_div').innerHTML = error.get_message();
}
This works great and when my Web method returns (a string), it always looks perfect. However, if one of my error messages from a my thrown exception contains a special character, it's displayed incorrectly in the browser. For example, if the error message were to contain the following:
That input isn’t valid! (that's an ASCII #146 in there)
It displays this:
That input isn’t valid!
Or:
Do you like Hüsker Dü? (ASCII # 252)
Becomes:
Do you like Hüsker Dü?
The content of the error messages comes from XML files with UTF-8 encoding:
<?xml version="1.0" encoding="UTF-8"?>
<ErrorMessages>
<Message id="invalid_input">Your input isn’t valid!</Message>
.
.
.
</ErrorMessages>
And as far as page encoding is concerned, in my Web.config, I have:
<globalization enableClientBasedCulture="true" fileEncoding="utf-8" />
I also have an HTTP Module to set L10n parameters:
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;
I've tried disabling this HTTP Module but the result is the same.
The values returned by the web service (in the l_errMsg variable) look fine in the VS debugger. It's just once the client script has a hold of, it displays incorrectly. I've used Firebug to look at the response and special characters are mangled in there, too. So I find it pretty strange that strings returned by my web method look fine, even if there's special characters in them. Yet when I throw an exception from the web method, special characters in its message are incorrect. How can I fix this?
Solution
Are you sure setting the "fileEncoding" is what you want, and not "responseEncoding"? Setting the fileEncoding determines how the web server will try to read physical .asmx/.aspx files from disk when it can't determine the encoding automatically. So, settings this to "utf-8" means you must save all your .asmx/.aspx files in utf-8. I don't think is relevant though.
The mangling you're seeing is when text encoded as utf-8 is parsed using an 8-bit encoding (i.e. an utf-8 bytestream is decoded using an 8-bit decoder, such as, in your case, iso-8859-1/Windows-1252). So it's possible that the HtmlEncode() you're doing before throw()ing the Exception is wrong about the intended output encoding. So what happens if you don't HtmlEncode() the error message?
(Technically, "ASCII # 252" isn't quite right; ASCII has 128 characters; the apostrophe you use is coming from an 8-bit encoding such as, in your case, iso-8859-1/Windows-1252.)
Are you sure you've disabled that HTTP Module correctly? This line looks like it could be causing the problem:
HttpContext.Current.Response.ContentEncoding = l_Enc;
...since it's most likely setting the output encoding to an 8-bit encoding (the ANSI code page equivalent).
To support as many cultures as possible, you should set the response encoding to utf-8. This is the most supported Unicode format in browsers (I daresay all modern browsers support it), and Unicode is the only alternative to local encodings. That said, I don't fully understand what HTTP Module you are using and why you need it, so the situation may be more complex than I think.