ASP.NET 4 Web Api:带反斜杠的路由
ASP.NET 4 WebApi: route with back slash
我有一个 WebApi 路由 api/{type}({id})/{prop}
我想用 url 来调用它,比如 /api/User(domain\username)/groups
- 关键点是 id
值中的“\”。我从客户端发送它 url-encoded 即:
api/User(domain%5Cusername)/groups
。但是这条路线被忽略了,我得到了 404。
如何将反斜杠传递到路由的参数中?
正如@ATerry 在评论中建议的那样,问题不在于 ASP.NET,而在于 HTTP.SYS + IIS。甚至在进入 IIS 之前,反斜杠被 HTTP.SYS 替换到正斜杠上。
我们可以在 UrlRewrite IIS 模块的帮助下解决这个问题,因为它可以访问原始(未解码)url.
对于我的示例,我提出了以下规则。
<rule name="allow backslash" stopProcessing="true">
<match url="api/(.*)\((.*)\)(.*)" />
<action type="Rewrite" url="api/{R:1}({C:1}{C:2}{C:3}){R:3}" logRewrittenUrl="true" />
<conditions>
<add input="{UNENCODED_URL}" pattern="\((.*)(%5C)(.*)\)" />
</conditions>
</rule>
它并不理想,因为它非常具体。拥有一个只处理 %5C
.
的通用规则会更有用
想法是用 %5C
捕获一个 url 并重写它以将其放回去。这有点奇怪,但它有效。
除了规则我们还需要在system.webServer
/security
/requestFiltering
中设置allowDoubleEscaping=false
:
<security>
<requestFiltering allowDoubleEscaping="true">
</requestFiltering>
</security>
使用此规则,进入 Mvc/Api 控制器的值将被编码(使用 %)。所以我们必须对其进行解码:
public virtual DomainResult GetObjectProp(string type, string id, string prop)
{
id = Uri.UnescapeDataString(id);
}
我有一个 WebApi 路由 api/{type}({id})/{prop}
我想用 url 来调用它,比如 /api/User(domain\username)/groups
- 关键点是 id
值中的“\”。我从客户端发送它 url-encoded 即:
api/User(domain%5Cusername)/groups
。但是这条路线被忽略了,我得到了 404。
如何将反斜杠传递到路由的参数中?
正如@ATerry 在评论中建议的那样,问题不在于 ASP.NET,而在于 HTTP.SYS + IIS。甚至在进入 IIS 之前,反斜杠被 HTTP.SYS 替换到正斜杠上。
我们可以在 UrlRewrite IIS 模块的帮助下解决这个问题,因为它可以访问原始(未解码)url.
对于我的示例,我提出了以下规则。
<rule name="allow backslash" stopProcessing="true">
<match url="api/(.*)\((.*)\)(.*)" />
<action type="Rewrite" url="api/{R:1}({C:1}{C:2}{C:3}){R:3}" logRewrittenUrl="true" />
<conditions>
<add input="{UNENCODED_URL}" pattern="\((.*)(%5C)(.*)\)" />
</conditions>
</rule>
它并不理想,因为它非常具体。拥有一个只处理 %5C
.
想法是用 %5C
捕获一个 url 并重写它以将其放回去。这有点奇怪,但它有效。
除了规则我们还需要在system.webServer
/security
/requestFiltering
中设置allowDoubleEscaping=false
:
<security>
<requestFiltering allowDoubleEscaping="true">
</requestFiltering>
</security>
使用此规则,进入 Mvc/Api 控制器的值将被编码(使用 %)。所以我们必须对其进行解码:
public virtual DomainResult GetObjectProp(string type, string id, string prop)
{
id = Uri.UnescapeDataString(id);
}