Перенаправление на URL с методом POST в Asp.Net Core

2

У меня простой URL-редиректор:

    private static void RedirectToAPI(RewriteContext context)
    {
        var request = context.HttpContext.Request;
        if (request.Path.Value.StartsWith("/apiendpoint", StringComparison.OrdinalIgnoreCase))
        {           
            var json = JsonConvert.SerializeObject(request.Path.Value
                .Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
                .Skip(1));
            var response = context.HttpContext.Response;

            response.Headers[HeaderNames.Location] = $"/custom";
            response.StatusCode = StatusCodes.Status301MovedPermanently;
            context.Result = RuleResult.EndResponse;
            using (var bodyWriter = new StreamWriter(response.Body))
            {
                bodyWriter.Write(json);
                bodyWriter.Flush();
            }
        }
    }

Проблема в том, что при перенаправлении на /custom url запрос имеет метод GET, тогда как для этого метода требуется POST.

Например, отправьте запрос GET на url/apiendpoint/first/second/third, затем перезаписывает ответ на перенаправление, соответственно, следующий запрос должен быть с методом POST, но теперь это GET.

Как я могу изменить метод запроса, который после ответа на запись в URL-адресе?

  • 0
    Вы пробовали request.Method = "POST" ?
  • 0
    @Gururaj да, ничего не меняется, все еще ПОЛУЧАЙ запрос.
Показать ещё 13 комментариев
Теги:
asp.net-core
redirect
url
url-rewriting

3 ответа

0

Можете ли вы установить правильный ответ @juunas, его ответ решил для меня, как вы можете видеть в моем примере кода.

internal class RedirectCultureRule : IRule
{
    private const string CultureKey = "culture";

    public void ApplyRule(RewriteContext context)
    {
        HttpRequest httpRequest = context.HttpContext.Request;
        httpRequest.Query.TryGetValue(CultureKey, out StringValues cultureValues);
        string culture = cultureValues;

        if (cultureValues.Count > 0 && culture.IsCultureMatch())
        {
            context.Result = RuleResult.ContinueRules;
            return;
        }

        Dictionary<string, string> queryParts = new Dictionary<string, string>();
        NameValueCollection queryString = HttpUtility.ParseQueryString(httpRequest.QueryString.ToString());

        foreach (string key in queryString)
        {
            queryParts[key.Trim()] = queryString[key].Trim();
        }

        if (!queryParts.ContainsKey(CultureKey))
        {
            queryParts[CultureKey] = CultureInfo.CurrentCulture.Name;
        }

        string query = $"?{string.Join("&", queryParts.Select(qp => $"{qp.Key}={qp.Value}"))}";

        if (query.Length > 1)
        {
            httpRequest.QueryString = new QueryString(query);
        }

        string url = UriHelper.GetDisplayUrl(httpRequest);

        HttpResponse httpResponse = context.HttpContext.Response;
        httpResponse.StatusCode = 308;
        httpResponse.Headers[HeaderNames.Location] = url;

        using (StreamReader requestReader = new StreamReader(httpRequest.Body))
        {
            using (StreamWriter responseWriter = new StreamWriter(httpResponse.Body))
            {
                string body = requestReader.ReadToEnd();
                responseWriter.Write(body);
                responseWriter.Flush();
            }
        }

        context.Result = RuleResult.EndResponse;
    }
}
-2

EDIT: Ах, только что проверил комментарии. Если исходным запросом является GET, это тоже не сработает, и вы не можете сообщить браузеру POST. Не без возврата представления, которое автоматически выполняет форму с помощью JavaScript.

Вам нужно вернуть 308, а не 301.

Вот измененный код:

private static void RedirectToAPI(RewriteContext context)
{
    var request = context.HttpContext.Request;
    if (request.Path.Value.StartsWith("/apiendpoint", StringComparison.OrdinalIgnoreCase))
    {           
        var json = JsonConvert.SerializeObject(request.Path.Value
            .Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
            .Skip(1));
        var response = context.HttpContext.Response;

        response.Headers[HeaderNames.Location] = $"/custom";
        response.StatusCode = 308;
        context.Result = RuleResult.EndResponse;
        using (var bodyWriter = new StreamWriter(response.Body))
        {
            bodyWriter.Write(json);
            bodyWriter.Flush();
        }
    }
}

308 - это постоянная переадресация, которая требует, чтобы браузер сохранял этот метод. https://httpstatuses.com/308

Временная версия - 307.

Способы удобства для этих перенаправлений доступны в MVC Core 2.0.0-preview1.

-2

Это пример кода

public class ConvertGetToPostHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Add your logic here to decide if the request Method needs to be changed
        // Caution: This works only if you're redirecting internally
        request.Method = HttpMethod.Post;
        return await base.SendAsync(request, cancellationToken);
    }
}

Вам нужно будет добавить обработчик в Handler Pipeline как

config.MessageHandlers.Add(new ConvertGetToPostHandler());

Кроме того, прочитайте эту документацию, чтобы получить представление о ее цели и использовании.

  • 0
    В ASP.NET Core нет DelegatingHandler. Вместо этого используются промежуточные программы
  • 0
    Извини друг. Похоже, сегодня не мой день. Извините, что потратил ваше время. Я еще не работал над Core :(
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню