Blazor WASM结合MudBlazor实现对象保存时的文件上传问题
Blazor WASM 上传文件与对象同步提交问题解决
问题背景
我拥有一个Blazor WASM核心托管应用,包含Blazor客户端应用和.NET服务端项目,尝试实现在用户保存对象时同时上传文件,通过客户端服务向服务端控制器发送请求。
初始代码实现
模型定义
public class MyObjectDTO : BaseModel<MyObjectDTO> { public int Id { get; set; } [Required] public string MyObjectName { get; set; } = string.Empty; public List<ItemDocumentDTO>? MyFiles { get; set; } } public class ItemDocumentDTO : BaseModel<ItemDocumentDTO> { public int Id { get; set; } [Required(ErrorMessage = "Document Name is required")] public string DocumentName { get; set; } = string.Empty; public IBrowserFile? File { get; set; } }
客户端服务代码
public async Task<ServiceResponse<int>> CreateNewObject(MyObjectDTO newObject) { using var client = await _httpClientFactory.CreateClientAsync("default"); var multipartContent = new MultipartFormDataContent(); if (newObject.MyFiles != null) { foreach(var item in newObject.MyFiles) { if(item.File != null) { var fileContent = new StreamContent(item.File.OpenReadStream()); multipartContent.Add(fileContent, "files", item.File.Name); } } } var result = await client.PostAsJsonAsync($"api/MyObject/create-item", new { createObject = newObject, filesContent = multipartContent }); if (result != null && result.Content != null) { var response = await result.Content.ReadFromJsonAsync<ServiceResponse<int>>(); if (response != null) { return response; } } return new ServiceResponse<int> { Success = false, Message = "Failed to create end item.", Data = 0 }; }
服务端控制器代码
[HttpPost("create-item")] public async Task<ActionResult<ServiceResponse<int>>> CreateItem([FromForm] MyObjectDTO createObject) { // 断点未触发,请求到达控制器前失败 return Ok(await this._newObjectService.CreateNewItem(createObject)); }
报错信息
提交请求时,浏览器控制台报错:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-987c028fd41bb0e6605243e6b5de5d4c-c7f26f97d41a2b54-00",
"errors": {
"MyObjectName": [
"The MyObjectName field is required."
]
} }
尽管MyObjectName值不为空且表单已通过验证,但仍出现此错误。
第一次修改尝试
按照建议调整代码后仍报错:
新增模型定义
public class YourRequestModelDTO { public ItemDTO createItem { get; set; } public List<IFormFile>? files { get; set; } public string? Key { get; set; } } public class ItemDTO : BaseModel<ItemDTO>{ public int Id { get; set; } [Required] public string ItemName { get; set; } = string.Empty; }
修改后的客户端服务代码
public async Task<ServiceResponse<int>> CreateNewItem(ItemDTO newItem) { using var client = await _httpClientFactory.CreateClientAsync("default"); using (MultipartFormDataContent content = new MultipartFormDataContent()) { var file = newItem.ItemDocuments.First().File; var fileContent = new StreamContent(file.OpenReadStream(1024 * 15)); fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType); content.Add( content: fileContent, name: "files", fileName: file.Name); content.Add(new StringContent(newItem.ItemName), "createItem.ItemName"); content.Add(new StringContent(newItem.EndDescription), "createItem.EndDescription"); try { var result = await client.PostAsync("api/MyItem/create-item", content); if (result != null && result.Content != null) { var response = await result.Content.ReadFromJsonAsync<ServiceResponse<int>>(); if (response != null) { return response; } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
修改后的服务端控制器代码
[Authorize] [HttpPost("create-item")] public async Task<ActionResult<ServiceResponse<int>>> CreateItem([FromForm] YourRequestModelDTO createItem) { return Ok(await this._itemService.CreateNewItem(createItem.createItem)); }
此时浏览器控制台仍报错:One or more validation errors occurred. 和 CreateItem.createItem: the createItem field is required.
最终解决方案
客户端服务调整代码
using (MultipartFormDataContent content = new MultipartFormDataContent()) { var file = newItem.ItemDocuments.First().File; var fileContent = new StreamContent(file.OpenReadStream(1024 * 15)); fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType); content.Add( content: fileContent, name: "files", // 需与API控制器参数名匹配 fileName: file.Name); var test = JsonConvert.SerializeObject(newItem); var itemContent = new StringContent(test, Encoding.UTF8, "application/json"); content.Add(itemContent, "NewItem"); }
服务端控制器调整代码
[Authorize] [HttpPost("create-item")] public async Task<ActionResult<ServiceResponse<int>>> CreateItem(){ var serializedObject = HttpContext.Request.Form["NewItem"]; // 在此处反序列化NewItem为对应的DTO对象 // 处理文件:通过HttpContext.Request.Form.Files获取上传的文件集合 return Ok(await this._itemService.CreateNewItem(/* 反序列化后的对象 */)); }
内容的提问来源于stack exchange,提问作者jason
相关产品推荐
相关产品推荐

