You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET 7中结合Refit使用[FromForm]实现文件上传

问题:.NET 7 Web API FormData端点通过Refit调用返回NotFound的解决方法

我正在开发基于.NET 7的Web API,其中有一个接收[FromForm]参数的端点,参数包含IFormFile、枚举和string类型。通过Swagger可正常调用该端点上传文件并填充信息,但使用Refit客户端调用时,两种尝试均返回NotFound异常。


API端代码

控制器实现

// FilesController
[HttpPost("/files", Name = nameof(UploadFile))]
public async Task<ActionResult<FileResponse>> UploadFile(
    [FromForm] UploadFileRequest request, CancellationToken cancellationToken)
{
 // 业务逻辑代码
}

请求模型与枚举定义

// 请求模型
public record UploadFileRequest
{
    public required IFormFile File { get; set; }
    public required FilePurpose Type { get; set; }
    public required string Description { get; set; }
}

// 枚举类型
public enum FilePurpose{
  Input,
  Output
}

Refit客户端的两种尝试

尝试1:使用封装的请求模型

[Multipart]
[Post("/files")]
Task<FileResponse> UploadFile(
    UploadFileRequestRefit request,
    CancellationToken cancellationToken = default);

public record UploadFileRequestRefit
{
    public required MultipartItem File { get; set; }
    public required FilePurpose Type { get; set; }
    public required string Description { get; set; }
}

尝试2:直接传递单个参数

[Multipart]
[Post("/files")]
Task<FileResponse> UploadFile(
    [AliasAs("file")] MultipartItem file,
    [AliasAs("type")] FilePurpose type,
    [AliasAs("description")] string description,
    CancellationToken cancellationToken = default);

解决方法

出现NotFound的核心原因是Refit生成的请求格式与API端点期望的FormData格式不匹配,尤其是参数名称大小写不匹配和枚举序列化方式错误,调整方案如下:

1. 修正请求模型版的实现

给请求模型的每个属性添加[AliasAs]特性,确保和API端模型的属性名完全一致(注意首字母大写),同时指定枚举的序列化方式:

[Multipart]
[Post("/files")]
Task<FileResponse> UploadFile(
    [Body] UploadFileRequestRefit request,
    CancellationToken cancellationToken = default);

public record UploadFileRequestRefit
{
    [AliasAs("File")]
    public required MultipartItem File { get; set; }
    
    [AliasAs("Type")]
    [EnumMember(Value = "{0}")] // 让枚举以字符串值传递
    public required FilePurpose Type { get; set; }
    
    [AliasAs("Description")]
    public required string Description { get; set; }
}

2. 修正直接传参版的实现

调整参数的AliasAs名称为大写,同时给枚举参数添加序列化配置:

[Multipart]
[Post("/files")]
Task<FileResponse> UploadFile(
    [AliasAs("File")] MultipartItem file,
    [AliasAs("Type")] 
    [Query(SerializationMethod = QuerySerializationMethod.ToString)] 
    FilePurpose type,
    [AliasAs("Description")] string description,
    CancellationToken cancellationToken = default);

3. 额外排查点

  • 检查Refit客户端的BaseAddress配置,避免路径拼接错误(比如BaseAddress末尾带/,接口路径又以/开头,会导致重复的斜杠)。
  • 确认HttpClient未被自定义拦截器修改FormData请求的结构。

内容的提问来源于stack exchange,提问作者Ana Mendes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:03:23