HttpClient кодирование параметров URL, содержащих /

#c# #asp.net-core-webapi #dotnet-httpclient #.net-5

Вопрос:

Я использую HttpClient (Dot Net 5) и пытаюсь получить объект из веб-службы DotNetCore, указав его идентификатор в URL-адресе.

  • Это работает, если идентификатор не содержит символов, которые нуждаются в кодировке.
  • Произойдет сбой (HTTP 404), если идентификатор содержит косую черту (/).
    • Диагностика веб-службы подтверждает, что запрос не доходит до метода.

Другие клиенты, такие как Почтальон или Свэггер, работают нормально.

Пример неудачи:

 string id = "Person/65-C";
var httpResponse = await httpClient.GetAsync(string.Format("/persons/{0}", System.Web.HttpUtility.UrlEncode(id)));
 

Комментарии:

1. Вы пробовали не кодировать его по URL-адресу? .NET может делать это автоматически для вас, и поэтому ваша строка получает двойное экранирование.

2. Не могли бы вы также поделиться кодом для части веб-сервиса?

3. @HereticMonkey Извините и спасибо за ваш комментарий. Я удалил свой ответ, так как он не дает четкого решения.

4. @Крис Феллоуз, я пытался, но не смог воспроизвести проблему на своей машине с помощью простого веб-api и простой консольной программы. Не могли бы вы поделиться дополнительной информацией о вашей настройке : какой веб-сервер вы используете (kestrel или iis). Также вы используете обратный прокси-сервер перед веб-сервером (например, nginx или apache). Если да, использовали ли ваши тесты с Postman URL обратного прокси-сервера или URL веб-сервера? (Я спрашиваю об этом, потому что nginx можно настроить для декодирования путей перед их передачей на веб-сервер).

5. @Крис Феллоуз, также, пожалуйста, запустите этот код, чтобы получить фактический URL-адрес, используемый для вызова веб var actualUri = (await client.GetAsync(string.Format("/persons/{0}", System.Web.HttpUtility.UrlEncode("Person/65-C")))).RequestMessage.RequestUri.AbsoluteUri; -сервиса . Как только у вас будет значение actualUri , можете ли вы сравнить его с тем, что отображается на Swagger в разделе Curl . Вы также можете просто использовать Curl напрямую для проверки ответа сервера : curl -X GET "${value of actualUri here}" -H "accept: text/plain"

Ответ №1:

Я предлагаю вам использовать [HttpGet("persons/{**value}")] атрибут в вашем серверном api.

Мой тестовый образец кода.

 [HttpGet("persons/{**value}")]
public string test(string value)
{
    return "userid: = "   value;
}
 

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Ответ №2:

Я столкнулся с той же проблемой. Потратили наши, чтобы найти решение, но безуспешно. В итоге я изменил свой маршрут и вместо этого преобразовал параметр маршрута в параметр строки запроса. Возможно, это не идеальное решение для каждого сценария, но в моем случае оно сработало.

Изменил маршрут с

 $"api/album/{HttpUtility.UrlEncode("a/b")}"
 

Для

 $"api/album/url=a/b"
 

И в контроллере

 [HttpGet]
public TestModel Get([FromQuery] string url)
{
}