Превышение длины Get-запроса при формировании returnURL .Net 6
На каждой странице у меня есть получение текущего адреса
//Текущий URL
string currentURL = Context.Request.GetDisplayUrl();
и передача его при переходе по сайту в параметре контроллера returnURL. Пример:
public async Task<IActionResult> IndexAsync ([CanBeNull] string returnURL, int page = 1)
{
//Проверка returnURL
returnURL ??= GetSiteMainPageUrl();
...
}
и ссылка на него
<a asp-action="Index" asp-area="account" asp-controller="Users" asp-route-returnURL="@currentURL" class="nav-link">
<span class="fas fa-users"></span>
Пользователи сайта
</a>
То есть получается вот такая ссылка:
https://localhost:44304/account/Users?returnURL=https%3A%2F%2Flocalhost%3A44304%2
При переходе на следующую страницу такая:
https://localhost:44304/account/Users/Filter?returnURL=https%3A%2F%2Flocalhost%3A44304%2Faccount%2FUsers%3FreturnURL%3Dhttps%253A%252F%252Flocalhost%253A44304%252
Вы, наверное, уже догадались, что в итоге ловлю
HTTP Error 404.15 - Not Found
Модуль фильтрации запросов настроен таким образом, чтобы не пропускать слишком длинные строки запросов.
и понятно из-за чего. Как можно передавать в returnURL все параметры запроса для страницы, исключая её returnURL или как организовать такие переходы по-другому. POST тоже не выход, так как он в итоге будет так загружать страницу, что проще от этой идеи отказаться...
ОБНОВЛЕНИЕ: Получается 2 выхода, как мне видится:
- Создать парсер текста, который будет находить второй returnURL и удалять его;
- Использовать middleware и session. С помощью 1-го дополнить контекст словарём, загружаемым из сессии (с чего начать?)
Ответы (1 шт):
Пока получилось решить вопрос (благодаря этому вопросу) так:
/// <summary>
/// Очищает URL, удаляя ненужные QueryString
/// </summary>
/// <param name="helper"><see cref="IUrlHelper"/></param>
/// <param name="context"><see cref="HttpContext"/></param>
/// <param name="url">Ссылка, которую нужно почистить</param>
/// <param name="clearQueryString">Массив ключей, которые нужно удалить</param>
/// <param name="getLocalURL">Возвращать только локальную ссылку</param>
/// <returns></returns>
[NotNull]
public static string ParseURLQuery([NotNull] IUrlHelper helper, HttpContext context, [CanBeNull] string url,
[NotNull] List<string> clearQueryString, bool getLocalURL = true)
{
//Получаю returnURL
url ??= "/";
//Если адрес локальный, то преобразую в полный
if (helper.IsLocalUrl(url))
url = $"{context.Request.Scheme}://{context.Request.Host}{url}";
//Создаю uri по адресу
Uri uri = new(url);
UriFormat format = UriFormat.UriEscaped;
//Формирую Uri-адрес сайта
string baseUri =
uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port,
format);
//Формирую локальную ссылку
string localUri = uri.GetComponents(UriComponents.Path, format);
//Создаю словарь запроса
Dictionary<string, StringValues> query = QueryHelpers.ParseQuery(uri.Query);
//Если он содержит параметр для очистки, то удаляю его
foreach (string s in clearQueryString.Where(s => query.ContainsKey(s)))
query.Remove(s);
//Запускаю построение новых параметров
QueryBuilder qBuilder = new(query);
//Создаю переменную-результат
string result = "";
//Если нужно получить полную ссылку
if (!getLocalURL)
result = baseUri;
//формирую переменную-результат
result = $"{result}/{localUri}{qBuilder.ToQueryString()}";
//Вывожу результат
return result;
}
Как его можно улучшить?