c# - API Controller POST 方法 multipart/form-data 在正文中使用边界获取消息

标签 c# controller multipartform-data .net-5 boundary

我在 API Controller 上开发 C# (.Net 5) 方法时遇到问题,该 Controller 可以管理具有“multipart/form-data”的请求;边界=边界'

我无法在客户端更改请求,我只能修改我的后端以适应它。

请求指定'Content-Type: multipart/form-data; boundary=boundary',它的正文中有一条我需要提取的 json 消息。

在请求的正文中,消息是这样的:

--boundary
Content-Disposition: form-data; name="ZZZZZZZZZZ"
Content-Type: application/json
Content-Length: 474

{
    //a well formed json
}
--boundary--

我可以使用以下代码获取:string dataMessage = new StreamReader(Request.Body).ReadToEndAsync().Result;

然后我可以使用 IndexOf 和 Substring 手动解析该字符串以仅提取 json 部分,然后使用 JsonConvert 将其转换为对象。

我想知道 .Net 上是否有一些选项可以自动执行此操作而无需手动解析字符串。我认为必须有某种方法来解释边界标记并获得直接json数据。但我找不到任何 :( 我想到了这一点,因为当使用 webhook.site 测试客户端请求时,它可以毫无问题地解析消息。

我的 Controller 定义是这样的

[ApiController]
[Route("api/[controller]")]
public class XXXXController : ControllerBase

方法是这样的

[HttpPost]
[Route("[action]")]
public IActionResult YYYYYYY()

我已经尝试指定模型绑定(bind)来更改行为,但我无法让它工作。

而且我在询问之前已经搜索了帮助:

感谢您的帮助!

最佳答案

默认情况下,.Net5 中不支持multi-part/form-data 媒体类型。因此,输入格式化程序应附加到 MvcBuilder

考虑到您无法操纵客户端,ApiMultipartFormDataFormatter这使得可以使用这种类型的输入格式。

  1. 添加包:

Install-Package ApiMultipartFormDataFormatter -Version 3.0.0

  1. Startup.cs 中配置格式化程序

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers(options =>
        {
            options.InputFormatters.Add(new MultipartFormDataFormatter());
        });
    }
    
  2. 假设上面提到的格式良好的 json 类似于下面的类:

    public class CustomContent
    {
        public string Name { get; set; }
    }
    

    因此,我们需要将它包装到另一个包含 this 作为参数的类中。 注意:库目前不支持反序列化,因此,将一个 getter-only 属性添加到返回反序列化对象的模型中。

    public class ViewModel
    {
        // Equivalent to ZZZZZZZZZZ
        public string SerializedContent { get; set; }
        public CustomContent Content => !string.IsNullOrEmpty(SerializedContent)
            ? JsonConvert.DeserializeObject<CustomContent>(SerializedContent)
            : null;
    }
    
  3. 修改 Action 以接受包装器模型。

    [HttpPost]
    [Route("[action]")]
    public IActionResult Parse(ViewModel vm)
    {            
        return Ok($"Received Name: {vm?.Content?.Name}");
    }
    

对应示例的工作cURL请求为:

curl --location --request POST 'http://localhost:25599/api/MultiPart/Parse' 

\
--header 'Content-Type: multipart/form-data; boundary=boundary' \
--data-raw '--boundary
Content-Disposition: form-data; name="SerializedContent"
Content-Type: application/json
Content-Length: 100

{
    "Name" : "Foo"
}
--boundary--'

响应应等于Received Name: Foo

关于c# - API Controller POST 方法 multipart/form-data 在正文中使用边界获取消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68834176/

相关文章:

javascript - 如何使用 react-native 为 FormData 发布数据数组

c# - EF Core 3.0 .Include 无法按预期工作且超慢

c# - 控制 dotnet core 的 ThreadPool 中的线程数

c# - 如何在包含回车符的 WPF GridView 中显示文本

javascript - 如何在 AngularJS 中动态更改 Controller 之间的数据

ruby-on-rails - 用于构建新操作的 rspec 匹配器

asp.net-mvc - ASP.NET MVC以编程方式获取 Controller 列表

Groovy 中的 HTTPBuilder 和 MultipartEntity/multipart 表单数据

google-apps-script - UrlFetchApp 在 Google Apps 脚本中上传文件 multipart/form-data

c# - 在 NHibernate 中为子查询使用接口(interface)