Search code examples
c#asp.net-coreblazorazure-cognitive-servicesblazor-client-side

Blazor WebAssembly PWA - IFormFile FromForm is always null


I have setup a Blazor WebAssembly ASP.Net Core hosted PWA project and am using Azure Cognitive Services in it. Therefore I have in one of my client-views a form where the user can upload an image and this will be referred to Azure.

In the razor-view I have this:

@inject HttpClient client;
@inject IFileReaderService FileReader;
@inject NavigationManager navi;

<div class="text-center">
    <input class="btn btn-secondary " name="file" @ref="InpReference" type="file" id="file-selector" placeholder="Brows" accept="image/*" capture="camera" @onclick="InputFile">

    @if (_fileSelected != false)
    {
        <input class="btn btn-primary" type="button" role="button" id="startbutton" @onclick="Upload" value="upload" />
    }
</div>

@code {
        private async Task Upload()
        {
            // content base structure
            MultipartFormDataContent content = new MultipartFormDataContent();
            content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
    
            
            foreach (/*IFileReference*/var fileReference in fileReferences)
            {
                Console.WriteLine("test1");
                // getting the file size
                IFileInfo fileinfo = await fileReference.ReadFileInfoAsync();
                Stream fileStream;
                var fileReferencesArray = fileReferences.ToArray();
                using (var fs = await fileReference.CreateMemoryStreamAsync((int)fileinfo.Size))
                {
                    Console.WriteLine("test2");
                    fileStream=new MemoryStream(fs.ToArray());
                }
                Console.WriteLine("test4" + fileinfo.Size);
                StreamContent sc = new StreamContent(fileStream, (int)fileStream.Length);
                content.Add(sc, "file", fileinfo.Name);
                Console.WriteLine("test5");
            }
            Console.WriteLine("test6");
            var response = await client.PostJsonAsync<List<Prediction>>("api/Azure/Prediction", content);
            Console.WriteLine(response.Count + " : " + response.GetType().ToString());
            foreach (var prediction in  response)
            {
                Console.WriteLine(prediction.Id + ":" + prediction.Name + "," + prediction.Probability.ToString());
            }
            navi.NavigateTo("detailView/");
    
    
        }
}

My WebApi Controller for the handling:

    ...
        [HttpPost]
        public List<Prediction> getPrediction([FromForm]IFormFile file)
        {
            if (file == null)
            {
                return new List<Prediction>();
            }
            List<Prediction> predicitions = azure_Client.GetPrediction(file.OpenReadStream());
            return predicitions;
        }
    ...

The problem is that the [FromForm]IFormFile file in the controller is always null. This is only null in the PWA project. I have set the same project up without PWA and it works, it is not null and it is getting the selected image from the view! What is the difference there and why isn't the HttpClient doing the same as in the Blazor WebAssembly ASP.Net Core hosted?


Solution

  • According to my test, if you want to upload file in Blazor WebAssembly ASP.Net Core hosted PWA, please refer to the following steps

    1. Client(I use the sdk Tewr.Blazor.FileReader)

      a. update Program.cs

      builder.Services.AddFileReaderService(options => {
                options.UseWasmSharedBuffer = true;
            });
            builder.Services.AddTransient(sp =>
                new HttpClient
                {
                    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
                });
      

      b. upload file razor-view

    @using System.IO
    @using Blazor.FileReader
    
    @inject HttpClient client;
    @inject IFileReaderService fileReader
    <h1>File uplaod Blzaor WebAssembly!</h1>
    <div class="row">
        <div class="col-4">
            <div class="form-group">
                <input type="file" name="image" @ref="inputReference" @onchange="async() =>await OpenFile()" />
                <ul>
                    <li>File Name: @fileName</li>
                    <li>Size: @size</li>
                    <li>Type: @type</li>
                </ul>
    
            </div>
            <button class="btn btn-block btn-success" @onclick="async() =>await UploadFile()"> Upload File</button>
            @if (!string.IsNullOrWhiteSpace(message))
            {
                <div class="alert alert-success">
                    File has been uplaoded
                </div>
    
            }
        </div>   
    </div>
    
    
    @code{
        ElementReference inputReference;
        string message = string.Empty;
        string fileName = string.Empty;
        string type = string.Empty;
        string size = string.Empty;
        Stream fileStream=null;
    
        async Task UploadFile()
        {
            var content = new MultipartFormDataContent();
            content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
            var sc = new StreamContent(fileStream, (int)fileStream.Length);
            content.Add(sc, "image", fileName);
    
    
            var response = await client.PostAsync("/upload", content);
            if (response.IsSuccessStatusCode) {
                message = "OK";
            }
    
        }
    
        async Task OpenFile()
        {
            var file = (await fileReader.CreateReference(inputReference).EnumerateFilesAsync()).FirstOrDefault();
    
            if (file == null) {
                return;
            }
    
            var fileInfo=await file.ReadFileInfoAsync();
            fileName = fileInfo.Name;
            type = fileInfo.Type;
            size = $"{fileInfo.Size} Bytes";
    
            using (var ms = await file.CreateMemoryStreamAsync((int)fileInfo.Size)) {
                fileStream = new MemoryStream(ms.ToArray());
            }
        }
    
    
    
    }
    
    1. Server

    API COntroller

     [HttpPost]
            public async Task<IActionResult> Post([FromForm(Name ="image")]IFormFile file) {
    
                if (file == null || file.Length == 0) {
                    return BadRequest("do not receive file");
                }
    
                var fileName = file.FileName;
                var extension = Path.GetExtension(fileName);
                var newFileName = $"{Guid.NewGuid()}{extension}";
                var filePath = Path.Combine(_env.ContentRootPath, "Images", newFileName);
                if (!Directory.Exists(Path.Combine(_env.ContentRootPath, "Images"))) {
                    Directory.CreateDirectory(Path.Combine(_env.ContentRootPath, "Images"));
                
                }
                using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) {
                    await file.CopyToAsync(stream);
                }
                
                return Ok(filePath);
            
            }
    
    1. Result

    enter image description here enter image description here