Параметр маршрута с косой чертой "/" в URL-адресе
Я знаю, что вы можете применить подстановочный знак в атрибуте маршрута, чтобы разрешить /
, например, ввод даты, например:
[Route("orders/{*orderdate}")]
Проблема с шаблоном применима только к последнему параметру в URI. Как решить проблему, если вы хотите иметь следующий URI:
[Route("orders/{orderdate}/customers")]
Update:
Я знаю, что есть несколько вариантов решения проблемы путем рефакторинга кода, поэтому, пожалуйста, не предлагайте какое-то решение:
- измените шаблон маршрута на
[Route("orders/customers/{orderdate}")]
- изменить дату на другой формат (например,
"dd-mm-yyyy"
)
Ответы
Ответ 1
@bet.. Я думаю, что genericUriParserOptions
больше не применимы к .net 4.5 или новее..
Также, как предлагает @JotaBe, вам может потребоваться правильно декодировать URL-запрос. В большинстве случаев %2F
будет автоматически переведен в косую черту '/'
. Так что, если вам нужно его избежать, вам нужно будет сначала декодировать символ '%'
.. так что ваш URL: будет выглядеть примерно так: www.domain.com/api/orders/23%252F06%252F2015/customers
Обратите внимание, что символы '%252F'
будут переведены в фактический '%2F'
РЕДАКТИРОВАТЬ
Хорошо, вот полное решение (попробовал и работает для меня):
-
Предполагая, что у вас есть конечная точка API, вот так:
[Route("orders/{date}/customers")]
public HttpResponseMessage Get(string date)
{
}
-
В requestPathInvalidCharacters
web.config вам нужно установить пустой requestPathInvalidCharacters
который указывает asp.net разрешить все запросы
<system.web>
<httpRuntime targetFramework="4.5" requestPathInvalidCharacters=""/>
</system.web>
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
-
Когда клиент отправляет запрос в API, вам необходимо убедиться, что экранирование '%'
выполняется следующим образом:
www.domain.com/api/orders/23%252F06%252F2015/customers
-
Затем вам нужно декодировать запрос
[Route("orders/{date}/customers")]
public HttpResponseMessage Get(string date)
{
DateTime actualDate = DateTime.Parse(System.Net.WebUtility.UrlDecode(date)); // date is 23/06/2015
}
Ответ 2
Как отмечено в комментарии @AlexeiLevenkov, это неправильно:
У вас не может быть параметра в URL, который принимает прямую косую черту, потому что это специальный символ, который разделяет каждый фрагмент URL. Таким образом, всякий раз, когда вы включаете этот символ в свой URL, появляются новые фрагменты, и один параметр не может включать несколько фрагментов.
Если вы хотите больше подробностей, прочитайте это, но это самые важные выдержки:
- URL-путь заканчивается первым
?
или #
найдено в URL. Таким образом, косые черты создают только фрагменты в разделе пути URL-адреса до появления или одного из этих символов. - Из раздела 3.4: Компонент запроса обозначается первым знаком вопросительного знака ("?") И завершается символом знака числа ("#") или концом URI.
Таким образом, строка запроса может включать косые черты, /
, если это необходимо, и они не будут определять сегменты пути вообще.
Вот некоторые решения вопроса:
- включите фрагменты для дня, месяца и года, например:
[Route("orders/{month}/{day}/{year}/customers")]
а затем создайте дату на стороне сервера - потребуйте, чтобы пользователь использовал другой разделитель, такой как тире или точка, который не создаст проблем, получите его в строке и проанализируйте его самостоятельно (или используйте свой собственный механизм связывания для поддержки этого формата)
- используйте расширение URL Rewrite, чтобы изменить URL до того, как он достигнет системы маршрутизации, и проанализируйте его, как описано в предыдущем решении (для этого требуется хостинг в IIS)
- получить его в виде строки запроса, то есть что-то вроде этого: ´? date = 02/03/2015´ (лучше кодировать)
ПРИМЕЧАНИЕ. В исходном вопросе было указано "строка запроса", а мой комментарий о кодировке ссылался на строку запроса, которая является последним сегментом URL-адреса после знака вопроса, если он присутствует, like &id=27
. Я исправил ваш вопрос, чтобы в нем не упоминалась "строка запроса", которая не была подходящим названием для того, что вам нужно
Ответ 3
Вы можете использовать следующий URI [Route("orders/{DD:int}/{MM:int}/{YY:int}}/customers")]
а затем используйте настраиваемое связующее устройство, чтобы взять DD/MM/YY
и превратить их в дату, которую вы можете связать в своем методе действий.
Вы можете выбрать, как вы хотите справиться с ограничениями (более строгие с помощью регулярных выражений) или использовать проверку и вернуть 400, если они не совпадают.
Более простой подход - взять Day/Month/Year
и поместить его в код.
Вот ссылка на связанный с привязкой к файлам.
Ответ 4
С# имеет свой собственный метод, который пропускает правила escape-последовательностей
название метода
Uri.UnescapeDataString (ваш параметр строки запроса)
Вы можете использовать его при получении значения параметров