ASP.NET MVC在IIS6上绝少出现因为文件编码问题而导致的乱码问题,即使出现,也可以通过web.config的配置或者修改文件编码来解决,然而今天碰到的这例乱码问题,却无法使用这些方法来解决,无论怎么修改,乱码依旧。让人懊恼不已!
问题是这样的:ASP.NET MVC2在IIS6上进行部署,由于系统还有一些暂时未能完全使用MVC架构的代码存在,就利用了IIS6中自定义错误页面的URL重定向机制,将404错误页面转发回系统页面进行处理,在系统中进行判定页面是否不存在或者重新配置页面地址重定向,让MVC Routing能够进行处理。想法是不错的,处理英文的时候也是非常顺畅的,但碰到中文的时候,系统就情不自禁的抽起疯来,根本就无法达到预期的效果。—— 一查,参数未解码的时候中文编码都是%ufffd
,一解码全是乱码,能达到预期效果反而奇怪了!
开始以为是配置上问题,检查了下config文件,发现request和response的Encoding都是UTF8,进而检查文件编码,也是UTF8,这和配置中的编码一致。理论上这样乱码应该不存在的,但理论往往和实际相差甚远!只好进一步检查,在历尽千辛万苦,最后发现问题原来出现在IIS的URL重定向上。当访问一个不存在的页面(含中文参数),IIS6会触发404错误,并将产生错误的内容重定向到指定的URL上,目标页面获取参数信息,但在处理中文时,需要进行解码,但根据IIS6定向过来的内容解码就会出现乱码,这就导致组合后的新地址经过MVC 路由后,无法正确的加载指定功能 —— 参数不对。
以前我一直的说法是找到问题就是成功解决问题的关键,这话的确没错,接下来要解决它,只需要找到为什么IIS6传递过来的内容会出现解码错误即可。然而,随着进一步的检查发现,问题远没有想象的那么简单,IIS6.0在处理字串的时候默认使用的是Unicode编码(注:这里比较乱,有说GBK,也有说GB2312,还有说是ASCII,谁知道请告诉我,IIS6使用的默认编码是什么?这里用Unicode)。这个编码和我们有什么关系么?—— 我现在是没有想出具体的关系的,但是肯定是有关系的。以下为本人观点,猜测成分比较大,如果你有更详细的这方面资料请分享,将非常感激。
在我们站点都使用UTF8的时候—— 这里我们需要补充个基础知识,UTF8的字符集是明显大于Unicode编码的。当IIS6检测到错误的时候,需要将UTF8转为IIS6的编码,并进行封装再转交给我们站点内处理,由于IIS6使用的是Unicode编码,在将UTF8字串转为Unicode时,因为字符集不够,所以出现无法转换现象,在无法转换是,系统用%ufffd
来表示未能转换的字符。因此使用Unicode处理数据,再转交给站点内模块,程序设置为UTF8编码,UTF8去解码Unicode编码字串,结果可想而知,解码出来的中文自然而然就是乱码。这个思路大概用下面的图来概括(注:图中用的是GBK表示)
这个图片描述的可能有误,但迄今为止尝试了很多各种编码的组合方式,都没有很好的将中文转成在程序中获取到的那种样子,所以也不能确定到底IIS6使用的是什么东西。
解决方法网上有提供一些,但他们能真正的解决问题吗?
1. 最多人的建议是使用UrlEncode方法将所有的中文进行编码之后传到服务端。
但这种方法对于自定义错误页面的方法根本就无法解决。IIS6同样会将URL中的中文变成乱码。
2. 另一种比较多的方法是在BeginRequest事件中处理,用Encoding去尝试转码来解决编码问题。
个人认为这个方法也没能真正解决问题,因为我们一旦获取到的是%ufffd
这种的参数时,就意味着我们的参数已经出现问题了。再说,这个方法和前一种方法一样,真正错误的是在IIS6中的自定错误页面过来的参数,在这之前已经出现错误,后面怎么弥补都无济于事。
调试可以发现,在Request对象中,虽然QueryString,Url中的所有的都是乱码,但是RawUrl是正常的。如下图:
经过多次的测试发现,如果要比较好的解决这个问题,可以使用以下两种方法:
1. 如果真的要在BeginRequest中处理乱码——当然,你也可以在你需要获取参数的时候进行处理,使用RawUrl。因为只有这个参数能够完整的保留中文信息。
2. 对当前处理逻辑调整,直接处理掉可以处理的页面内容,而不要依赖IIS6的自定义错误页面来解决在程序中原本是非错误的页面,比如:数据库中页面,先要进行404跳转之后,再进入指定页面再来处理,这种处理方式比较闹心,但当下却还是有一些在用,我这篇文章就是这么来的。
当然了,上面的建议都是理想状态的,对于现存的项目来说,要实现不是一时半会,还需要仔细斟酌。针对我当前特定版本的解决方法,项目是MVC的,直接在Route中添加了对应规则,让这些都转入指定的模块中"销毁"吧,这和上述第二点原理一样,但却治不了根。
根据网上的一些信息综合起来看,这个问题应该是出自IIS6内部,不仅是中文,就连很多国际友人在做开发的时候也碰到过各种各样的Unicode Problem。有些反馈是说在IIS7下面没有这种现象,这个我没有测试,如果哪位有条件的可以测试下。
问题暂时解决了,可以先休息会,毕竟这个问题折腾了我好几天啊!
参考:
CSDN 设置404页面所导致的乱码问题的帖子: http://bbs.csdn.net/topics/390358009
IIS.NET上面关于Unicode字符丢失的帖子:http://forums.iis.net/t/1085091.aspx/1