asp.net-coreasp.net-core-webapic#-9.0iformfile

How to extend .NET Core IFormFileCollection


I'm developing an ASP.NET Core 5 Web API project, I want to save a post which contains multiple files. Each file should includes name and title.

Here is my code:

public class PostDTO
{
    public Guid? CategoryId { get; set; }
    public Guid UserID { get; set; }
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public string Tags { get; set; }

    public IFormFileCollection FileList { get; set; }
}

[HttpPost]
public async Task<IActionResult> Post([FromForm] PostDTO postDTO)
{
    if (postDTO == null)
        throw new ArgumentNullException(nameof(postDTO));

    List<PostAttachmentFileDataStructure> FileList = new();

    if (postDTO.FileList != null)
        foreach (var Attachment in postDTO.FileList)
            FileList.Add(PostAttachmentFileDataStructure.Create(Guid.NewGuid(), "FileTitle", Attachment));

        try
        {
            await commandBus.Send(PostCommand.Create(Guid.NewGuid(), postDTO.PostTitle, postDTO.PostContent, postDTO.CategoryId, postDTO.UserID, postDTO.Tags.NormalizedInput(), FileList));
        }
        catch (Exception)
        {
            return StatusCode(500);
        }

        return Ok();
}

As you know IFormFile and IFormFileCollection don't have any properties like Title. So I want to extend IFormFileCollection to add another property called Title.

Is there any way to do that?


Solution

  • In backend:

    Instead of

    public class PostDTO
    {
        public Guid? CategoryId { get; set; }
        public Guid UserID { get; set; }
        public string PostTitle { get; set; }
        public string PostContent { get; set; }
        public string Tags { get; set; }
    
        public IFormFileCollection FileList { get; set; }
    }
    

    and

    public async Task<IActionResult> Post([FromForm] PostDTO postDTO){...}
    

    you should use:

    public class PostDTO
    {
        public Guid? CategoryId { get; set; }
        public Guid UserID { get; set; }
        public string PostTitle { get; set; }
        public string PostContent { get; set; }
        public string Tags { get; set; }
        public List<FileInfo> FileInfos { get; set; }
    }
    
     public class FileInfo
        {
            public string title{ get; set; }
            public string filename { get; set; }
        }
    

    and

    public async Task<IActionResult> Post( IFormCollection dto){...}
    

    then in body you can convert data to your dto

    PostDTO postDTO = JsonConvert.DeserializeObject<PostDTO>(dto["data"]);
    

    for access to uploaded files you can use

    dto.Files
    

    In frontend:

        const data = {
                categoryId: "1",
                postTitle: "1",
                postContent: "1",
                userId: "1",
                tags: "1",
                fileInfos: [
                  { title: "1", fileName: "1" },
                  { title: "2", fileName: "2" },
                ],
              };
              const formData = new FormData();
              formData.append("data", JSON.stringify(data));
              formData.append("files", "file that has been uploaded");
    
          axios
            .post("your api URL", formData)