Blazor WASM: File Upload - MultipartFormDataContent.Add() throws internal Invalid JSON exception
See original GitHub issueIs there an existing issue for this?
- I have searched the existing issues
Describe the bug
Uploading a file results in Invalid JSON
in internal code.
ImageUploader.razor
:
<InputFile OnChange="UploadFiles" multiple />
ImageUploader.razor.cs
:
using BlazorTests.Shared;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
namespace BlazorTests.Client.Shared
{
public partial class ImageUploader : ComponentBase
{
private List<File> files = new();
private List<UploadResult> uploadResults = new();
private int maxAllowedFiles = 10;
private bool shouldRender;
protected override bool ShouldRender() => shouldRender;
private void UploadFiles(InputFileChangeEventArgs e)
{
shouldRender = false;
long maxFileSize = 1024 * 1024 * 15;
var upload = false;
using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
{
if (uploadResults.SingleOrDefault(
f => f.FileName == file.Name) is null)
{
try
{
var fileContent =
new StreamContent(file.OpenReadStream(maxFileSize));
fileContent.Headers.ContentType =
new MediaTypeHeaderValue(file.ContentType);
files.Add(new() { Name = file.Name });
try // This is the block that throws. Note that the exception is not catched and the app breaks.
{
content.Add(
content: fileContent,
name: "\"files\"",
fileName: file.Name);
}catch(JsonException ex)
{
Console.WriteLine(ex.Message);
}
upload = true;
}
catch (Exception)
{
uploadResults.Add(
new()
{
FileName = file.Name,
ErrorCode = 6,
Uploaded = false
});
}
}
}
shouldRender = true;
}
private class File
{
public string Name { get; set; }
}
}
}
The code is taken from documentation.
Expected Behavior
No exception, obviously.
Steps To Reproduce
https://github.com/Grizzlly/BlazorTests
Exceptions (if any)
When I debug and try to upload a file, I get this:
.NET Version
6.0.100
Anything else?
.NET SDK (reflecting any global.json): Version: 6.0.100 Commit: 9e8b04bbff
Runtime Environment: OS Name: Windows OS Version: 10.0.22000 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.100\
Host (useful for support): Version: 6.0.0 Commit: 4822e3c3aa
.NET SDKs installed: 3.1.415 [C:\Program Files\dotnet\sdk] 5.0.104 [C:\Program Files\dotnet\sdk] 5.0.209 [C:\Program Files\dotnet\sdk] 5.0.303 [C:\Program Files\dotnet\sdk] 5.0.403 [C:\Program Files\dotnet\sdk] 6.0.100 [C:\Program Files\dotnet\sdk]
.NET runtimes installed: Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.0-rc.1.21451.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.0-rc.1.21451.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
To install additional .NET runtimes or SDKs: https://aka.ms/dotnet-download
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:36 (22 by maintainers)
Yes. The reason why that works isn’t because of
StringContent
but rather becauseawait fileContent.ReadAsStringAsync()
ensures we await the streaming initialization.content: new StringContent(await fileContent.ReadAsStringAsync(), Encoding.UTF8, "application/octet-stream")
Yes we’ll be discussing potentially bringing this into a future patch release in the new year once team members return from seasonal holidays. Fortunately it won’t affect everyone as those who do the actual upload end up reading the stream as well per the sample:
This is present in the official docs (but not in the sample you provided). This is likely also the explanation for why you and I were seeing this error reproduce, however Luke was not (as Luke was likely using the
FileUpload2
component exactly as documented with the upload section).https://github.com/dotnet/aspnetcore/pull/39060 will ensure we don’t get the un-necessary exceptions, however the fact that we threw an exception in the first place in .NET 6 and not .NET 5 was bothering me. I wanted to make sure this wasn’t indicative of a deeper issue. Fortunately it’s not.
EndInvokeJS
failing as the pending task is missing. We throw an exception saying we haven’t read the contents of the call. This is what https://github.com/dotnet/aspnetcore/pull/39060 fixes.e.File.OpenReadStream()
which requests the stream, and JS sends back the__jsStreamReferenceLength
and__jsObjectId
. However in between the request and response, we cancel (ex. end of function or a variety of other reasons).I’ve minimized the repro to the following.
Exceptions from investigation
Stack trace on what’s removing the pending task:
Stack trace with args: