将 POST 请求从 asp.net 核心控制器转发到不同的 URL

Posted

技术标签:

【中文标题】将 POST 请求从 asp.net 核心控制器转发到不同的 URL【英文标题】:Forward POST request from asp.net core controller to different URL 【发布时间】:2019-12-04 11:55:56 【问题描述】:

我想在不使用中间件的情况下将传入的 POST 请求“按原样”(包括标头、正文、源数据)转发到我的 asp.net 核心控制器到不同的 URL。

我为 asp.net 找到了一个示例:https://philsversion.com/2012/09/06/creating-a-proxy-with-apicontroller/

但这不适用于 asp.net 核心,因为调用 返回等待 http.SendAsync(this.Request); 在 asp.net core 中接受一个 HttpRequestMessage 并且 Request 对象的类型是 HttpRequest。

我还发现了一些代码,它从 HttpRequest 创建了一个 HttpRequestMessage,请参阅:Convert Microsoft.AspNetCore.Http.HttpRequest to HttpRequestMessage

使用此代码,接收端点(我转发到的)获取正文,但没有获取表单字段。

检查类 HttpRequestMessage 我发现它不包含 FormFields 的属性。

[Microsoft.AspNetCore.Mvc.HttpPost]
[NrgsRoute("api/redirect-v1/key")]
public async Task<HttpResponseMessage> Forward(
   [FromUri] string key,
   CancellationToken cancellationToken)

   // the URL was shortened, we need to get the original URL to which we want to forward the POST request
   var url = await _shortenUrlService.GetUrlFromToken(key, cancellationToken).ConfigureAwait(false);

     using (var httpClient = new HttpClient())
     
         var forwardUrl = new Uri(url);
         Request.Path = new PathString(forwardUrl.PathAndQuery);

         // see: https://***.com/questions/45759417/convert-microsoft-aspnetcore-http-httprequest-to-httprequestmessage
         var requestMessage = Request.ToHttpRequestMessage();
         return await httpClient.SendAsync(requestMessage, cancellationToken);

         // Problem: Forwards header and body but NOT form fields
     
 

预期的结果是在我的接收端点我有相同的 - 标题 - 身体 - 表单域 与原始 POST 请求一样。

【问题讨论】:

感谢您的问答!你拯救了我的一天! 【参考方案1】:

我最终做了以下事情:

[HttpPost]
[NrgsRoute("api/redirect-v1/key")]
public async Task<RedirectResult> Forward(string key, CancellationToken cancellationToken)

    var url = await _shortenUrlService.GetUrlFromToken(key, cancellationToken).ConfigureAwait(false);
    if (string.IsNullOrEmpty(url))
        throw new BadRequestException($"Could not create forward URL from parameter key", "redirect-error");

    using (var httpClient = new HttpClient())
    
        var forwardUrl = new Uri(url);
        Request.Path = new PathString(forwardUrl.PathAndQuery);

        HttpResponseMessage responseMessage;
        if (Request.HasFormContentType)
            responseMessage = await ForwardFormData(key, httpClient, forwardUrl, cancellationToken);
        else
            responseMessage = await ForwardBody(key, httpClient, cancellationToken);

        var queryParams = forwardUrl.GetQueryStringParams();
        var lUlr = queryParams["lurl"];
        return new RedirectResult(lUlr);
    


private async Task<HttpResponseMessage> ForwardFormData(string key, HttpClient httpClient, Uri forwardUrl, CancellationToken cancellationToken)

    var formContent = new List<KeyValuePair<string, string>>();
    HttpResponseMessage result;

    if (Request.ContentType == "application/x-www-form-urlencoded")
    
        foreach (var formKey in Request.Form.Keys)
        
            var content = Request.Form[formKey].FirstOrDefault();
            if (content != null)
                formContent.Add(new KeyValuePair<string, string>(formKey, content));
        
        var formUrlEncodedContent = new FormUrlEncodedContent(formContent);
        result = await httpClient.PostAsync(forwardUrl, formUrlEncodedContent, cancellationToken);
    
    else
    
        var multipartFormDataContent = new MultipartFormDataContent();
        foreach (var formKey in Request.Form.Keys)
        
            var content = Request.Form[formKey].FirstOrDefault();
            if (content != null)
                multipartFormDataContent.Add(new StringContent(content), formKey);
        

        result = await httpClient.PostAsync(forwardUrl, multipartFormDataContent, cancellationToken);
    

    return result;


private async Task<HttpResponseMessage> ForwardBody(string key, HttpClient httpClient, CancellationToken cancellationToken)

    // we do not have direct access to Content, see: https://***.com/questions/41508664/net-core-forward-a-local-api-form-data-post-request-to-remote-api

    var requestMessage = Request.ToHttpRequestMessage();
    return await httpClient.SendAsync(requestMessage, cancellationToken);

【讨论】:

以上是关于将 POST 请求从 asp.net 核心控制器转发到不同的 URL的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个数组作为 POST 请求参数从 AJAX 发送到 MVC 控制器(ASP .NET Core 3.1 剃须刀)?

如何从axios.post发送简单的值到asp.net核心?

Asp.net core MVC post 参数始终为空

如何将简单值从 axios.post 发送到 asp.net 核心?

带有asp .net核心的防伪令牌jquery ajax

[转] ASP.NET MVC 模型绑定的功能和问题