假设我有一个这样的ViewModel来自ASP. NET MVC中提交的表单:
public class EditProfileViewModel
{
public string DisplayName { get; set; }
public IFormFile Photo { get; set; }
}
我可以在控制器中很容易地接收到:
public async Task<IActionResult> OnPost([FromForm] EditProfileViewModel edits)
{
// edits contains form data, great
}
但是现在我想把它转发到后端API,也使用ASP. NET。包括文件上传。最简单的方法似乎是使用MultipartFormDataContent创建一个新的HttpClient表单POST。但据我所知,虽然从表单内容到模型类的转换在接收请求时是透明的,但创建MultipartFormDataContent需要对键值对进行硬编码。
我知道这样做是可能的:
var form = new MultipartFormDataContent()
form.Add(new StringContent(edits.DisplayName), "displayName")
var content = new StreamContent(edits.Photo.OpenReadStream());
content.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType)
form.Add(content, "photo") // Is this the right capitalization ?? See how error prone this is?
var result = await client.PostAsync("some-api", form);
但是,对于重复的声明,这是冗长且容易出错的。此外,要在接收端使用相同的模型类进行反序列化,需要了解转换的魔力。
有没有更好的方法将模型类转换回MultipartFormDataContent?或者,如果这是一个XY问题,将此表单模型转发到后端ASP的更好方法。NET API?
需要转换魔法的知识
这就是问题所在——MultipartFormDataContent
可以用来将表单发布到任何网络应用程序,代码不知道潜在的解析魔法,因为它需要被告知接收端期望它的格式。
一个web框架可以区分大小写,而另一个需要小写或完全匹配的大小写。或者对于数组,一个可以支持字段名称的重复(name="foo"
,name="foo"
,...),另一个可能需要一个[]
后缀(name="foo[]"
,name="foo[]
,...)和又一个可能需要索引(name=foo[0]
,name=foo[1]
,...)。
更不用说多级属性了:name="foo.bar"
,name="foo_bar"
,...
因此,您必须编写自己的属性到fieldname映射代码,知道您发布到哪个框架。