RedirectToAction()打破了变音符号

时间:2015-12-02 22:01:52

标签: c# utf-8 asp.net-mvc-5 azure-web-sites

注意: 导致问题的 RedirectToAction(),但在web.config重写规则

原始问题: 使用RedirectToAction()时出现奇怪的行为,我无法在本地重现(调试)。在某些时候,我的路由值从äa更改为äa,但仅在服务器(Azure)上更改。我添加了日志记录以确定确切位置并最终在此处:

RedirectToAction("square", new { id = criteria.Trim().ToLower() });

在本地,这会重定向到/find/square/äa,但在服务器上会以/find/square/äa结尾。我记录了每一步,当我的字符串传递给RedirectToAction时,它仍然完好无损(即使在Trim()ToLower()之后),但在重定向后被破坏。我正在使用默认路由

routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }

控制器find,操作square和ID äa(在本例中)

这对我来说非常令人惊讶,因为对于变音符号和UTF-8,.NET通常非常小心和强大。我特别迷失在这里,因为我无法在本地重现这个问题。我认为这是一个服务器设置,但Azure此时非常稀疏。之前有没有人经历过类似的行为?

1 个答案:

答案 0 :(得分:0)

这是我的代码的一部分,我没有发布,重写规则。在我仔细研究了Fiddler中的重定向之后,我才发现了这一点。事实上,我在故意触发之后发现了一个额外的重定向,它是由我的一个重写规则引起的:

    <rule name="Lowercase Path" stopProcessing="true" >
      <match url="[A-Z]" ignoreCase="false" />
      <conditions>
        <add input="{REQUEST_METHOD}" matchType="Pattern" pattern="POST" ignoreCase="true" negate="true" />
        <add input="{URL}" pattern="^.*\.(axd|css|js|jpg|jpeg|png|gif|txt|xml|svg|pdf)$" negate="true" ignoreCase="true" />
      </conditions>
      <action type="Redirect" url="{tolower:{URL}}" redirectType="Permanent" />
    </rule>

实际上它是以下一行:

<action type="Redirect" url="{tolower:{URL}}" redirectType="Permanent" />

一旦禁用此规则,一切正常。我不使用{ToLower:}的其他规则不会产生任何问题。我不确定,为什么这不会破坏本地的东西。在进行研究的过程中,我发现了一篇文章,描述了微软是如何修补破坏的重写模块,这会导致与变音符号类似的问题。这是猜测,但也许我的azure实例上的重写版本未修补 - 或者它是完全不同的。

不幸的是,使用{tolower:{URL}}重写规则的替代方案很少,所以我不得不做一个相当丑陋的解决方法并在Global.asax.cs中检查我的网址,如下所示:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        var pathAndQuery = System.Web.HttpUtility.UrlDecode(Request.Url.PathAndQuery);

        if (pathAndQuery == null || Regex.IsMatch(pathAndQuery, @"^.*\.(axd|css|js|jpg|jpeg|png|gif|txt|xml|svg|pdf)$"))
        {
            return;
        }

        if (Regex.IsMatch(pathAndQuery, ".*[A-Z].*"))
        {
            Response.Redirect(pathAndQuery.ToLower(), false);
            Response.StatusCode = 301;
        }
    }

我对这种方法并不完全满意;它感觉很臭,但在我找到更好的解决方案之前,这已经足够了。