Mar*_*ell 44 asp.net iis unicode url asp.net-mvc
上下文:在IIS中运行的ASP.NET MVC,带有UTF-8%编码的URL.
使用标准项目模板和类似的测试操作HomeController:
public ActionResult Test(string id)
{
return Content(id, "text/plain");
}
Run Code Online (Sandbox Code Playgroud)
这适用于大多数%编码的UTF-8路由,例如:
http://mydevserver/Home/Test/%e4%ba%ac%e9%83%bd%e5%bc%81
Run Code Online (Sandbox Code Playgroud)
与京都expected的预期结果
但是使用路线:
http://mydevserver/Home/Test/%ee%93%bb
Run Code Online (Sandbox Code Playgroud)
网址未正确收到.
旁白:%ee%93%bb是%编码的代码点0xE4FB; 基本 - 多语种平面,私人使用区域; 但最终 - 一个有效的unicode代码点; 你可以手动验证,或通过:
string value = ((char) 0xE4FB).ToString();
string encoded = HttpUtility.UrlEncode(value); // %ee%93%bb
Run Code Online (Sandbox Code Playgroud)
现在,接下来发生的事情取决于Web服务器; 在Visual Studio开发服务器(也称为cassini)上,id接收到正确的字符串 - 长度为1的字符串,包含代码点0xE4FB.
但是,如果我在IIS或IIS Express中执行此操作,我会得到一个不同的id,特别 "î“»"是代码点:0xEE,0x201C,0xBB.您将立即将第一个和最后一个识别为我们的百分比编码字符串的开头和结尾...那么中间发生了什么?
好:
它在我看来非常像IIS在处理我的网址时执行了某种报价翻译.现在也许这可能在一些场景中使用(我不知道),但当它发生在%-encoded的UTF-8块中间时肯定是一件坏事.
请注意,这HttpContext.Current.Request.Raw 也表明已经发生了这种翻译,所以这看起来不像是一个MVC错误; 还要注意Darin的评论,强调它在url的路径vs查询部分中的工作方式不同.
所以(两人):
id = Encoding.UTF8.GetString(Encoding.Default.GetBytes(id));
Run Code Online (Sandbox Code Playgroud)
这将为您提供原始ID.IIS对路径字符使用默认(ANSI)编码.您的网址编码字符串使用它进行解码,这就是为什么你会得到一个奇怪的东西.
要获取原始ID,您可以将其转换回字节并使用utf8编码获取字符串.
ISAPI过滤器是ANSI API - 您可以使用API获取/设置的所有值都必须是ANSI.是的,我知道这很令人震惊; 毕竟,它是2006年,现在一切都是用Unicode ...但请记住,这个API起源于十多年前,当时几乎没有任何东西是32位,更不用说Unicode了.另外,请记住,ISAPI直接操作的HTTP协议是ANSI而不是Unicode.
编辑:既然你提到它适用于大多数其他字符,所以我假设IIS有某种编码检测机制,在这种情况下失败.作为一种解决方法虽然你可以在id前面添加这个char,然后你可以很容易地检测出问题是否发生(如果缺少这个char).不是一个非常理想的解决方案但它会起作用.然后,您可以在ASP.NET MVC中编写自定义模型绑定器和包装类,以使您的使用代码更清晰.
最终,为了解决这个问题,我不得不使用request.ServerVariables["HTTP_URL"]一些手动解析,以及一堆错误处理回退(另外补偿 中的一些相关故障Uri)。不是很好,但只影响极少数尴尬的请求。