Asp.net core FromForm未反序列化要在路由中使用的FormData对象';s参数?
我在asp.net核心后端服务器中有一个更新路由Asp.net core FromForm未反序列化要在路由中使用的FormData对象';s参数?,asp.net-core,Asp.net Core,我在asp.net核心后端服务器中有一个更新路由 [HttpPatch("{id}")] public async Task<IActionResult> Update([FromForm] GearItemViewModel gearItem) { ... } 参数已成功填充 我可以从请求对象手动反序列化gearItem对象: JsonConvert.DeserializeObject<GearItemViewModel>(Request.Form["gear
[HttpPatch("{id}")]
public async Task<IActionResult> Update([FromForm] GearItemViewModel gearItem)
{
...
}
参数已成功填充
我可以从请求对象手动反序列化gearItem对象:
JsonConvert.DeserializeObject<GearItemViewModel>(Request.Form["gearItem"]);
JsonConvert.DeserializeObject(Request.Form[“gearItem]”);
你知道为什么这可能不起作用吗?根据我使用asp.net core FromForm accepts application/x-www-form-Url编码内容的经验。。。。。如果你想使用json,你可以用FromBody来代替。为什么它不起作用 你的第一个行动方法是 公共异步任务更新([FromForm]GearItemViewModel gearItem) 通常,它将接受
应用程序/x-www-form-urlencoded
或多部分/表单数据。但是,当使用application/x-www-form-urlencoded
时,不能同时发送图像文件(除非对图像文件进行编码,例如base64
,但这并不好)。由于同样的原因,无法在application/json
中发送有效负载
这意味着您的操作方法需要多部分/表单数据中的数据,如下所示:
POST /.../Update HTTP/1.1
Content-Type: multipart/form-data; boundary=----My.Boundary
------My.Boundary
Content-Disposition: form-data; name="id"
1
------My.Boundary
Content-Disposition: form-data; name="name"
tst
------My.Boundary
Content-Disposition: form-data; name="price"
30
------My.Boundary
Content-Disposition: form-data; name="inStock"
false
------My.Boundary
Content-Disposition: form-data; name="gearImages"; filename="1.jpg"
Content-Type: application/octet-stream
{bytes-of-your-image1}
------My.Boundary
Content-Disposition: form-data; name="gearImages"; filename="2.jpg"
Content-Type: application/octet-stream
{bytes-of-your-image2}
------My.Boundary
Content-Disposition: form-data; name="gearImages"; filename="3.jpg"
Content-Type: application/octet-stream
{bytes-of-your-image3}
------My.Boundary--
您需要如下构造FormData(我只是复制并粘贴您的代码,只需稍作修改)
然后发送FormData
,您将自动获得有效负载:
this.http.patch<GearItem>(`${this.merchandiseUrl}/${gearItem.id}`, this.selectedFileFormData)
.subscribe(res => {
...
})
假设您有4种齿轮尺寸:
var gearSizes: GearSize[] = [
{id:1,available:true, color:"red",size:Size.S},
{id:2,available:false, color:"blue",size:Size.XS},
{id:3,available:true, color:"green",size:Size.XXL},
{id:4,available:true, color:"yellow",size:Size.NONE},
];
要发送这些齿轮尺寸,只需创建具有尺寸[index]形式的字段。属性
:
// a helper function that appends its fields to formdata
appendOneGearSize(formData: FormData, index: Number, size:GearSize){
formData.append(`sizes[${index}].id`,size.id.toString());
formData.append(`sizes[${index}].available`,size.avaiable.toString());
formData.append(`sizes[${index}].color`,size.color.toString());
formData.append(`sizes[${index}].size`,size.size.valueOf().toString());
}
for(let index=0; index < gearSizes.length; index++){
this.appendOneGearSize(this.selectedFileFormData,index,gearSizes[index]);
}
//将其字段附加到formdata的辅助函数
附录GearSize(formData:formData,索引:编号,大小:GearSize){
append(`size[${index}).id`,size.id.toString());
append(`size[${index}).available`,size.available.toString());
append(`size[${index}].color`,size.color.toString());
append(`size[${index}).size`,size.size.valueOf().toString());
}
对于(让索引=0;索引
最后,这里是服务器端操作方法:
public async Task<IActionResult> Update([FromForm] GearItemViewModel gearItem)
{
...
}
公共异步任务更新([FromForm]GearItemViewModel gearItem)
{
...
}
工作演示:
@O.MeeKoh在我的asp.net核心操作中,我可以预期以下操作是否有效?:是的,它应该按预期工作。@O.MeeKoh其中gearItem将自动反序列化并填充参数?:[FromForm]
属性指示模型绑定器从表单(位于Request.Body
中)绑定参数。因为您在多部分/表单数据中发送有效负载
,ASP.NET核心能够找到所有相关字段并自动为您创建gearItem
实例。@O.MeeKoh我相信有两种方法可以做到这一点。但是在我编写代码并测试它之前,您能告诉我GearItem
class&GearItemSize
的定义吗?听起来像是GearItem
的属性是列表大小
?@O.MeeKoh我的回复太长了,所以我更新了我的答案。请检查:)@O.MeeKoh很高兴听到它有帮助:)
public class GearItemViewModel
{
public long Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public bool InStock { get; set; }
public IList<IFormFile> GearImages {get;set;}
}
this.selectedFileFormData.append("id","1");
this.selectedFileFormData.append("name","tst");
this.selectedFileFormData.append("price","30");
this.selectedFileFormData.append("inStock","false");
for (let index = 0; index < 3; index++) {
this.selectedFileFormData.append("gearImages", this.filesObj[index]);
}
var formElement = document.getElementById("yourFormId");
var selectedFileFormData= new FormData(formElement);
this.http.patch<GearItem>(`${this.merchandiseUrl}/${gearItem.id}`, this.selectedFileFormData)
.subscribe(res => {
...
})
// typescript
enum Size { NONE = 0, XS = 1, S = 2, XXL = 6 }
interface GearSize
{
id : Number,
available: boolean,
color : string,
size: Size,
}
var gearSizes: GearSize[] = [
{id:1,available:true, color:"red",size:Size.S},
{id:2,available:false, color:"blue",size:Size.XS},
{id:3,available:true, color:"green",size:Size.XXL},
{id:4,available:true, color:"yellow",size:Size.NONE},
];
// a helper function that appends its fields to formdata
appendOneGearSize(formData: FormData, index: Number, size:GearSize){
formData.append(`sizes[${index}].id`,size.id.toString());
formData.append(`sizes[${index}].available`,size.avaiable.toString());
formData.append(`sizes[${index}].color`,size.color.toString());
formData.append(`sizes[${index}].size`,size.size.valueOf().toString());
}
for(let index=0; index < gearSizes.length; index++){
this.appendOneGearSize(this.selectedFileFormData,index,gearSizes[index]);
}
public async Task<IActionResult> Update([FromForm] GearItemViewModel gearItem)
{
...
}