如何在.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
相关产品推荐
相关产品推荐

