Search code examples
blazorsyncfusion-blazor

SyncFusion: SfUploader


The SfUploader component from SyncFusion seems to have a lot of great built in features, however it seems to be missing one key one, and that is to send metadata along with the file.

To start, I'm working with .Net 6 and Blazor WASM. I've followed along with the "Getting Started" and have the component on the screen. It appropriately sends the file from the client to the server. I can hit a breakpoint and see the filename, content length, etc.

I chatted with the support on the site, and they sent me this link, but it does not work either.

So, my question is: Does anyone know how to add custom data to a "Save" call from an SfUploader component, and access it at the server?

As a hack, I was considering adding a JSON object instead of the filename. Please help me not do that.

Client code:

@page "/"

<SfUploader ID="UploadFiles">
    <UploaderEvents FileSelected="onFileSelect"></UploaderEvents>
    <UploaderAsyncSettings SaveUrl="api/SampleData/Save">
    </UploaderAsyncSettings>
</SfUploader>

@code {
    private void onFileSelect(SelectedEventArgs args)
    {
        args.CustomFormData = new DocumentDTO { Id = Guid.NewGuid(), 
                                                Description = "A really cool document", 
                                                Type = "WebUpload" };
    }

    public class DocumentDTO
    {
        public Guid Id { get; set; }
        public string Type { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
    }
 }

Server Code:

[ApiController]
[Route("api/[controller]")]
public class SampleDataController : ControllerBase
{
    [HttpPost("[action]")]
    public async void Save(IList<IFormFile> UploadFiles)
    {
        foreach (var file in UploadFiles)
        {
            var filename = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
            filename = Environment.CurrentDirectory + $@"\{filename}";
            Console.WriteLine("Where's my custom Data?");
        }
    }
}

Solution

  • The key bits that I was missing before was that there is a parameter on the SelectedEventsArgs of "CurrentRequest" which is the Header (thanks Mohammed).

    Additionally, since the Header is string based, the "object" has to be serialized to a string on the client, and deserialized at the server.

    This means that our onFileSelect method turns into:

    private void onFileSelect(SelectedEventArgs args)
    {
        List<DocumentDTO> documents = new();
        foreach (var file in args.FilesData)
        {
            DocumentDTO document = new DocumentDTO { Id = Guid.NewGuid(), Type = "WebUpload", Description = file.Name };
            documents.Add(document);
        }
        args.CurrentRequest = new List<object> { new { Documents = JsonSerializer.Serialize(documents) } };
    }
    

    and the controller method into

        [HttpPost("[action]")] public async void Save(IList<IFormFile> UploadFiles)
        {
            var jsonString = Request.Headers["documents"];
            var data = JsonSerializer.Deserialize<List<DocumentDTO>>(jsonString);
            foreach (var file in UploadFiles)
            {
                //Do Stuff
            }
        }