RestSharp 106.2.2发送带文件和JSON请求缺失boundary问题求助
我正在构建一个跨.NET Framework和.NET Standard的封装库,通过SendEmail函数向Azure Function的HTTP端点发送JSON载荷及多个文件。但使用RestSharp 106.2.2发送请求时,请求未携带boundary信息,导致Azure Function初始化MultipartMemoryStreamProvider失败。
控制台测试应用
private static void Main(string[] args) { var emailService = new EmailService(); var email = new MicroserviceMailMessage( "from@test.com", "to@test.com", "Test Subject from Framework App", "Test Body from Framework App", true, DateTime.Now ); email.Attachments.Add(new Attachment(@"c:\Temp\soccor5.jpg")); emailService.SendEmail(email); }
封装库代码
public void SendEmail(MicroserviceMailMessage email) { var client = new RestClient("http://localhost:7071/api"); var request = new RestRequest("SendEmail", Method.POST); var transformedEmail = TransformEmail(email); request.AlwaysMultipartFormData = true; request.AddHeader("Content-Type", $"multipart/form-data"); foreach (var attachment in email.Attachments) { var inline = attachment.ContentDisposition.Inline ? "inline." : ""; request.Files.Add(new FileParameter { Name = $"attachments.{inline}{attachment.Name}", Writer = (s) => { attachment.ContentStream.CopyTo(s); attachment.ContentStream.Dispose(); }, ContentType = attachment.ContentType.ToString(), ContentLength = attachment.ContentStream.Length, FileName = attachment.Name }); } request.AddParameter("email", $"{JsonConvert.SerializeObject(transformedEmail)}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); }
Azure接收函数
[FunctionName("EmailReceiver")] public static async Task<HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, ... ) { ... var provider = new MultipartMemoryStreamProvider(); await req.Content.ReadAsMultipartAsync(provider); // Fails on this line ... }
对比RestSharp 105.2.3(或Postman)发送的请求,其包含正确的boundary信息,而106.2.2的请求缺失该信息,报错:
Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter.\r\nParameter name: content
我尝试过降级到RestSharp 105.2.3,该版本在.NET Framework下可正常工作,但我需要封装库兼容.NET Framework和.NET Standard,因此该方案无法彻底解决问题。
解决方案
问题的核心在于RestSharp 106+版本的行为变化:如果你手动设置Content-Type为multipart/form-data,会完全覆盖库自动生成的包含boundary的头信息。以下是具体的修复步骤:
移除手动添加的Content-Type头
删除这行代码,让RestSharp自动生成带boundary的Content-Type:// 删掉这行 request.AddHeader("Content-Type", $"multipart/form-data");修正JSON参数的添加方式
你当前使用ParameterType.RequestBody添加JSON参数,这会和multipart表单结构冲突。应该将其作为表单字段添加:// 替换原来的AddParameter(RequestBody) request.AddParameter( "email", JsonConvert.SerializeObject(transformedEmail), ParameterType.GetOrPost );优化文件参数添加(可选)
可以使用RestSharp内置的AddFile方法简化文件添加逻辑,避免手动创建FileParameter:foreach (var attachment in email.Attachments) { var inline = attachment.ContentDisposition.Inline ? "inline." : ""; request.AddFile( name: $"attachments.{inline}{attachment.Name}", writer: s => { attachment.ContentStream.CopyTo(s); attachment.ContentStream.Dispose(); }, fileName: attachment.Name, contentLength: attachment.ContentStream.Length, contentType: attachment.ContentType.ToString() ); }
原理说明
在RestSharp 105.x版本中,即使手动设置了multipart/form-data的Content-Type,库仍然会自动追加boundary参数。但106+版本为了更灵活地支持自定义头,改变了这个行为——手动设置的Content-Type会完全替代自动生成的头,导致缺失boundary。而当你移除手动设置的头后,RestSharp会在检测到multipart请求(设置了AlwaysMultipartFormData = true且包含文件/表单参数)时,自动生成包含随机boundary的正确Content-Type头。
内容的提问来源于stack exchange,提问作者tokyo0709

