Запросы к контроллерам с умлаутами (спецсимволами) не работают с телом - PullRequest
0 голосов
/ 05 сентября 2018

С учетом следующего контроллера (созданного с помощью 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:

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.

ОБНОВЛЕНИЕ 27-06-2019:

ASP.NET Core 2.2:

  • POST работает сейчас
  • GET не: - (

https://github.com/aspnet/AspNetCore/issues/11640

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Я не могу объяснить, почему запросы специальных символов прерываются, только если передано тело. Это, вероятно, ошибка!

Я бы хотел описать обходной путь. Первое, что происходит:

  1. Клиент (например, почтальон) отправляет UTF-8 "Städte".
  2. Отправляется поток байтов UTF-8 "Städte": 53 74 c3 a4 64 74 65 (для UTF-8 "ä" требуется 2 байта: c3 a4!)
  3. По некоторым причинам ядро ​​ASP.MVC принимает кодовую страницу 8859-1 (Latin-1), а не UTF-8 в URI: поэтому 53 74 c3 a4 64 74 65 становится "Städte". Только для запросов с телами!

Именно поэтому я добавил [Route("api/Städte")] в контроллер, который позволяет Почтальону получить статус 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    ß
0 голосов
/ 05 сентября 2018

не уверен, пытались ли вы использовать строку [] вместо IEnumarable. хотя это то же самое,

Кроме того, устанавливаете ли вы тип содержимого "application / json" в заголовке при создании сообщения?

например. "Content-Type": "применение / JSON"

...