使用Asp.Net Core中的POST方法重定向到URL

时间:2017-06-01 12:23:27

标签: c# url redirect url-rewriting asp.net-core

我有简单的网址重写器:

    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 rewriter响应之后?

4 个答案:

答案 0 :(得分:1)

您可以将@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;
    }
}

答案 1 :(得分:0)

这是示例代码

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添加到Handler Pipeline

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

另外,请仔细阅读documentation以了解其目的和用法。

答案 2 :(得分:0)

编辑:啊,刚才检查了评论。如果初始请求是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中找到。

答案 3 :(得分:0)

如果使用ASP.NET Core 2.0,则有RedirectPermanentPreserveMethod,您可以here对其进行阅读。如果不支持此方法,则可以尝试手动进行。