对带有变音符号(特殊字符)的控制器的请求不适用于正文

时间:2018-09-05 10:47:17

标签: c# asp.net-core asp.net-core-mvc asp.net-mvc-routing

给出以下控制器(使用Visual Studio 15.8.2创建→WebApi模板):

[Route("api/[controller]")]
[ApiController]
public class StädteController : ControllerBase
{
    private static readonly List<string> Städte = new List<string>{"Berlin","Hamburg","München","Köln","Frankfurt","Stuttgart","Düsseldorf","Dortmund","Essen"};

    // GET api/Städte
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return Städte;
    }

    // Post api/Städte/Leipzig
    [HttpPost("{id}")]
    public void Post(string id)
    {
        if (!Städte.Contains(id))
            Städte.Add(id);
    }

    // Post api/Städte
    [HttpPost]
    public void Post([FromBody] IEnumerable<string> städte)
    {
        Städte.AddRange(städte?.Except(Städte) ?? Enumerable.Empty<string>());
    }
}

任何没有有效负载的请求都将起作用(返回OK 200):

  • GET https://localhost:44301/api/Städte
  • GET https://localhost:44301/api/St%C3%A4dte
  • POST https://localhost:44301/api/Städte/Leipzig
  • POST https://localhost:44301/api/St%C3%A4dte/Leipzig

正文为无效的请求(返回未找到404):

  • POST https://localhost:44301/api/Städte

    ["Dresden", "Chemnitz"]
    
  • POST https://localhost:44301/api/St%C3%A4dte

    ["Dresden", "Chemnitz"]
    

使用PUT会产生相同的结果!将ä重命名为ae可以,但是我不喜欢!

有人知道如果控制器的动作需要一个主体,为什么路由会中断吗?向客户提供变音符的URI的最佳解决方法是什么?


ASP.NET Core Web服务器日志:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://localhost:44301/api/St��dte application/json 23
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[0]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Builder.RouterMiddleware[1]
      Request did not match any routes.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HLGJ46FC5IM0" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 11.5071ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HLGJ46FC5IM0", Request id "0HLGJ46FC5IM0:00000002": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HLGJ46FC5IM0", Request id "0HLGJ46FC5IM0:00000002": done reading request body.
info: Microsoft.AspNetCore.Server.Kestrel[32]
      Connection id "0HLGJ46FC5IM0", Request id "0HLGJ46FC5IM0:00000002": the application completed without reading the entire request body.

2 个答案:

答案 0 :(得分:0)

不确定是否尝试使用string []而不是IEnumarable。虽然一样,

还要在发布文章时在标题中将内容类型设置为“ application / json”吗?

例如“ Content-Type”:“ application / json”

答案 1 :(得分:0)

我无法解释为什么仅在传递正文时特殊字符请求才会中断。 这可能是一个错误!

我想描述一种解决方法。首先会发生什么:

  1. 客户(例如邮递员)发送UTF-8“Städte”。
  2. 发送“Städte”的UTF-8字节流:53 74 c3 a4 64 74 65(UTF-8“ä”需要2个字节:c3 a4!)
  3. 由于某些原因,ASP.MVC Core假定代码页8859-1(Latin-1)而不是URI中的UTF-8:因此53 74 c3 a4 64 74 65变为“Städte”。仅适用于带有身体的请求!

这就是为什么我向控制器添加[Route("api/Städte")]的原因,该机制使Postman获得状态200(确定):

[Route("api/Städte")] // UTF-8 "ä" (0xc3a4) → ISO-8859-1 "ä".
[Route("API/STÄDTE")] // UTF-8 "Ä" (0xc384) → ISO-8859-1 "Ä".

[Route("api/[controller]")] // Default.
[ApiController]
public class StädteController : ControllerBase
{
    //...
}

注意:URL编码的请求默认情况下始终有效!!!因此,您无需添加[Route("api/St%C3%A4dte")][Route("API/ST%C3%84DTE")]


对于诸如此类的其他问题:使用ISO-8859-1代码页撰写您的变音符号。这是摘录:

UTF-8 → Binary → 8859-1
----------------------
ä       C3 A4    ä
Ä       C3 84    Ä
ö       C3 B6    ö
Ö       C3 96    Ö
ü       C3 BC    ü
Ü       C3 9C    Ãœ
ß       C3 9F    ß