How to programmatically upload a file in .NET 5 to a .NET 5 Rest API without losing content?

Viewed 1971

I created a .NET 5 REST Api. I can easily upload files from swagger. That is working fine. When debugging, I can see that the byte array is not empty. Here is the Controller method:

[Route("api/[controller]")]
[ApiController]
public class ImageController : ControllerBase
{

    // POST api/<ImageController>
    [HttpPost]
    public void Post([FromForm] UserModel info)
    { 
        var memoryStream = new MemoryStream();
        info.Avatar.CopyTo(memoryStream);
        var bytes = memoryStream.ToArray();
    }
}

This is the UserModel:

public class UserModel
{
    [FromForm(Name = "avatar")]
    public IFormFile Avatar { get; set; }

    [FromForm(Name = "name")]
    public string Name { get; set; }
}

I also tried to upload a file programmatically. This is not entirely working. When putting breakpoints in the controller method, I see that the byte array is empty. So the call itself is working but the data is not entering.

Here is the source code of the .NET 5 Console application to upload files.

As explained, this does something useful as it really calls the REST API which I can see by putting breakpoints in the controller method. However, my controller method does not get any data. The byte array is empty.

    private static async Task TryUpload()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:5000");
            string filePath = "C:\\Users\\daan1982\\Pictures\\RiderStart.png";
            var fileStream = File.Create(filePath);
            using (var content =
                new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
            {
                content.Add(new StreamContent(fileStream), "avatar", "RiderStart.png");

                var result = await client.PostAsync("/api/Image", content);
                var request = result.RequestMessage;
            }
        }
    }

    static async Task Main(string[] args)
    {
        await TryUpload();
        Console.WriteLine("Hello World!");
    }

As I named the content "avatar" in the upload and also in the request model, this should work fine. However, it does work but not fine as the byte array is always empty.

What am I doing wrong? And how can I fix this?

2 Answers

That's how it worked for me.

    static async Task Main(string[] args)
    {
        await TryUpload();
    }

    private const string Boundary = "EAD567A8E8524B2FAC2E0628ABB6DF6E";

    private static readonly HttpClient HttpClient = new()
    {
        BaseAddress = new Uri("https://localhost:5001/")
    };

    private static async Task TryUpload()
    {
        var requestContent = new MultipartFormDataContent(Boundary);
        requestContent.Headers.Remove("Content-Type");
        requestContent.Headers.TryAddWithoutValidation("Content-Type", $"multipart/form-data; boundary={Boundary}");

        var fileContent = await File.ReadAllBytesAsync(@"<path to file\Unbenannt.PNG");
        var byteArrayContent = new ByteArrayContent(fileContent);
        byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");

        requestContent.Add(byteArrayContent, "avatar", "Unbenannt.PNG");

        var postResponse = await HttpClient.PostAsync("/api/Image", requestContent);
    }
Related