You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 04:15:57