views:

1510

answers:

3

Greetings!

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? Thanks in advance.

+1  A: 

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.

bzlm
A: 

If I don't HtmlEncode(), the problem is the same. What has me baffled is why does the mangling only happen when my Web Method throws an exception, but not when it successfully returns its value? To add, when it returns its value, it gets the content from similar XML files with UTF-8 encoding.

Bullines
A: 

You're right. Commenting out:

HttpContext.Current.Response.ContentEncoding = l_Enc;

allows it to work properly. So then what would the best way to set the response ContentEncoding be, considering I need to support 20 or so cultures?

Bullines