我有一个AJAX表单,它将表单数据发布到本地API网址:/api/document
。它包含一个文件和一个自定义ID。我们只想获取确切收到的请求,并将其转发到example.com:8000/document/upload
的远程API。
是否有一种简单的方法可以使用Asp.NET Core实现对远程API的请求“转发”(或代理?)?
下面我们想到简单地使用Web API Http客户端来获取请求然后重新发送它(通过这样做我们希望能够例如从后端附加私有api密钥 ),但似乎无法正常工作,PostAsync
不接受Request
。
POST http://localhost:62640/api/document HTTP/1.1
Host: localhost:62640
Connection: keep-alive
Content-Length: 77424
Accept: application/json
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryn1BS5IFplQcUklyt
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8,fr;q=0.6
------WebKitFormBoundaryn1BS5IFplQcUklyt
Content-Disposition: form-data; name="fileToUpload"; filename="test-document.pdf"
Content-Type: application/pdf
...
------WebKitFormBoundaryn1BS5IFplQcUklyt
Content-Disposition: form-data; name="id"
someid
------WebKitFormBoundaryn1BS5IFplQcUklyt--
我们的.NET Core后端有一个简单的“转发到另一个API”的目的。
public class DocumentUploadResult
{
public int errorCode;
public string docId;
}
[Route("api/[controller]")]
public class DocumentController : Controller
{
// POST api/document
[HttpPost]
public async Task<DocumentUploadResult> Post()
{
client.BaseAddress = new Uri("http://example.com:8000");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.PostAsync("/document/upload", Request.Form);
if (response.IsSuccessStatusCode)
{
retValue = await response.Content.ReadAsAsync<DocumentUploadResult>();
}
return retValue;
}
}
我们有一个GET请求(此处未转载)可以正常使用。因为它不必从本地POST数据中获取数据。
如何简单地传递传入的本地HttpPost请求并将其转发到远程API?
我在stackoverflow或网络上搜索了很多,但所有这些资源都是关于将Request.Content
转发到遥控器的旧资源。
但是在Asp.NET Core 1.0上,我们无法访问Content
。我们只能检索Request.Form
(也不是Request.Body
),然后将其作为PostAsync
方法的参数接受:
无法从Microsoft.AspNetCore.Http.IformCollection转换为 System.Net.Http.HttpContent
我有想法直接将请求传递给postAsync:
无法从Microsoft.AspNetCore.Http.HttpRequest转换为 System.Net.Http.HttpContent
我不知道如何根据我收到的本地请求重建预期的HttpContent
。
有关信息,当我们使用自定义Id
和上传的文件发布有效的表单数据时,远程(example.com)API响应为:
{
"errorCode": 0
"docId": "585846a1afe8ad12e46a4e60"
}
答案 0 :(得分:6)
好的,首先创建一个视图模型来保存表单信息。由于涉及文件上传,请在模型中包含IFormFile
。
public class FormData {
public int id { get; set; }
public IFormFile fileToUpload { get; set; }
}
模型绑定器应该选择类型并使用传入数据填充模型。
更新控制器操作以接受模型并通过将内容复制到新请求来代理数据。
[Route("api/[controller]")]
public class DocumentController : Controller {
// POST api/document
[HttpPost]
public async Task<IActionResult> Post(FormData formData) {
if(formData != null && ModelState.IsValid) {
client.BaseAddress = new Uri("http://example.com:8000");
client.DefaultRequestHeaders.Accept.Clear();
var multiContent = new MultipartFormDataContent();
var file = formData.fileToUpload;
if(file != null) {
var fileStreamContent = new StreamContent(file.OpenReadStream());
multiContent.Add(fileStreamContent, "fileToUpload", file.FileName);
}
multiContent.Add(new StringContent(formData.id.ToString()), "id");
var response = await client.PostAsync("/document/upload", multiContent);
if (response.IsSuccessStatusCode) {
var retValue = await response.Content.ReadAsAsync<DocumentUploadResult>();
return Ok(reyValue);
}
}
//if we get this far something Failed.
return BadRequest();
}
}
您可以根据需要包含必要的异常处理程序,但这是如何向前传递表单数据的最小示例。