Redirect to URL with POST method in Asp.Net Core

Viewed 17690

I have simple url rewriter:

    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();
            }
        }
    }

The problem is, when it redirects to /custom url, request has method GET, while this method require POST.

For example, send GET request to url /apiendpoint/first/second/third, then rewriter responds to redirect, accordingly, the following request must be with method POST, but now, it is GET.

How can I change method of request, which is after url rewriter response?

4 Answers

Can you set @juunas answer as a correct answer, his answer solved it for me as you can see in my example code.

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;
    }
}

If using ASP.NET Core 2.0 there is RedirectPermanentPreserveMethod, you can read about it here. If this method is not supported you can try doing it manually.

Related