问题是路由属性参数不接受任何保留字符,即使它们是 URL 编码的:
https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
这将起作用:
https://localhost:44349/files/?fileName=mydocument%2B%23%26.docx&access_token=test-token
[Route("files/")]
[HttpGet]
public async Task<string> GetFileInfo2(string fileName, string access_token)
{
return "Test";
}
这不起作用:
https://localhost:44349/files/mydocument%2B%23%26.docx?access_token=test-token
[Route("files/{fileName}/")]
[HttpGet]
public async Task<string> GetFileInfo(string fileName, string access_token)
{
return "Test";
}
使用 WebClient 代理调用从 Javascript 前端到 C# 后端的完整示例:
Javascript:
let fileName = encodeURIComponent('mydocument+#&.docx');
fetch(`files?fileName=${fileName}&access_token=test-token`)
.then(function (response) {
return response.json();
})
.then(function (myJson) {
console.log(JSON.stringify(myJson));
});
C#:
[Route("files/")]
[HttpGet]
public async Task<string> GetFileInfo(string fileName, string access_token)
{
using (WebClient client = new WebClient())
{
var host = $"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}";
var data = client.DownloadString($"{host}/proxy/files/?fileName={HttpUtility.UrlEncode(fileName)}&access_token={HttpUtility.UrlEncode(access_token)}");
return data;
}
}
[AllowAnonymous]
[Route("proxy/files/")]
[HttpGet]
public async Task<string> ProxyGetFileInfo(string fileName, string access_token)
{
return "MyValues";
}
为什么不允许使用这些字符以及为什么需要首先处理它:
URI 语法中不允许使用的排除的 US-ASCII 字符:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
字符“#”被排除在外,因为它用于将 URI 与片段标识符分隔开。百分比字符“%”被排除在外,因为它用于转义字符的编码。换句话说,“#”和“%”是必须在特定上下文中使用的保留字符。
不明智的字符列表是允许的,但可能会导致问题:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
在查询组件中保留的字符和/或在 URI/URL 中具有特殊含义的字符:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
上面的“保留”语法类是指在 URI 中允许使用但在通用 URI 语法的特定组件中可能不允许使用的那些字符。“保留”集中的字符并非在所有上下文中都保留。例如,主机名可以包含可选的用户名,因此它可能类似于ftp://user@hostname/
“@”字符具有特殊含义的地方。
资源:
https://stackoverflow.com/a/13500078/3850405