ASP.Net Ajax and Response.Write or response filters The message received from the server could not be parsed.

I've built a TranslationFilter object that tries to.. well... translate ASP.Net pages. Everything ran smoothly until I had to use ASP.Net Ajax. I got the infamous error "Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.".
Starting analysing the problem, I soon understood that the Ajax requests go through the same Response mechanism as a normal page request, but the output is different. In case of normal page requests you get the HTML of the page, while in Ajax requests you get something formated like this:
contentLength|controlType|controlID|content|
If one uses Response.Write, the text is inserted both in the page HTML and the Ajax request format, resulting in something like "blablabla10|updatePanel|UpdatePanel1|0123456789" which cannot be parsed correctly and results in an error. The ScriptManager.IsInAsyncPostBack property shows us if the request is Ajax or not, so we can condition the Response.Write on this.
Also, if changing the content with a HttpResponse.Filter, the length of the content is no longer equal with the declared value. So what must be done is first detect if the content is Ajax. Unfortunately we cannot check the state of the ScriptManager from inside the HttpResponse.Filter, but we can check the format of the string to modify, then modify the content AND the contentLength, else it will all result in error.
Update: the content might not be changed by you! As one of the people asking me for help on the chat discovered, the web server provider might want to put in some ads, regardless if the request is an Ajax one, thus breaking the format. You need to patch the javascript ajax engine in order to work, that means changing the content the javascript function will get in order to not cause errors. You may find the solution here.
As an example, here is my Translate method:
private string RecursiveTranslateAjax(string content)
{
Regex reg = new Regex(@"^(\d+)\|[^\|]*\|[^\|]*\|",
RegexOptions.Singleline);
Match m = reg.Match(content);
if (m.Success)
{
int length = To.Int(m.Groups[1]);
reg = new Regex(
@"^(\d+)(\|[^\|]*\|[^\|]*\|)(.{" + length + @"})\|"
, RegexOptions.Singleline);
m = reg.Match(content);
if (m.Success)
{
string trans = Translate(m.Groups[3].Value);
return trans.Length + m.Groups[2].Value
+ trans + "|"
+ RecursiveTranslateAjax(content.Substring(m.Length));
}
}
return Translate(content);
}
Update:
I met this problem also when in the page there were Unicode characters. Everything works perfectly, then you can't postback anything, because some user text contains Unicode chars. The solution I used for this was to get the offending text (whether in Page.Render or in some other places based on specific situations) and take every character and check if it is ASCII. Web Pages should be UTF8 so any character bigger than 127 should be translated into a web page Unicode char &#[char code];
The code:
string s=[my string]
StringBuilder sb=new StringBuilder();
for (int c=0; c<s.Length; c++)
{
if (s[c]>127) sb.Append("&#"+((int)s[c])+";");
else sb.Append(s[c]);
}
s=sb.ToString();