Upload file in ASP.NET Core
Tags: aspnet, aspnetcore, upload
Published: 2022-01-25 12:15:08

One task of mine includes uploading file in `ASP.NET Core 5`. Last time I did file upload in `ASP.NET`, I did it with `IFormFile`. However, this time I preferred to make a research if anything is changed so far. I came to sample code from [*Microsoft*](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-6.0) which is based a non-argument action. I copied the *MS* to following sample and put an `IFromFile` sample besides it to be referenced together. 

```c#
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace upload.Controllers
{
    [ApiController]
    public class UploaderController : ControllerBase
    {
        [HttpPost]
        [Route("UploadModelBinding")]
        public async Task<IActionResult> UploadModelBinding(ICollection<IFormFile> files)
        {
            //model binding or model validation

            try
            {
                long size = files.Sum(f => f.Length);
                var fileName = Path.GetRandomFileName();
                var saveToPath = Path.Combine(Path.GetTempPath(), fileName);

                foreach (var formFile in files)
                {
                    if (formFile.Length > 0)
                    {
                        using (var stream = new FileStream(saveToPath, FileMode.Create))
                        {
                            await formFile.CopyToAsync(stream);
                        }
                    }
                }

                return Ok(new { count = files.Count, fileName, size, saveToPath });
            }
            catch (Exception exp)
            {
                return BadRequest("Exception generated when uploading file - " + exp.Message);
            }
        }

        [HttpPost]
        [Route("UploadNoArg")]
        public async Task<IActionResult> UploadNoArg()
        {
            //no-argument action

            var request = HttpContext.Request;

            if (!request.HasFormContentType ||
                !MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) ||
                string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
            {
                return new UnsupportedMediaTypeResult();
            }

            var reader = new MultipartReader(mediaTypeHeader.Boundary.Value, request.Body);
            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
                    out var contentDisposition);

                if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals("form-data") &&
                    !string.IsNullOrEmpty(contentDisposition.FileName.Value))
                {
                    var fileName = Path.GetRandomFileName();
                    var saveToPath = Path.Combine(Path.GetTempPath(), fileName);

                    using (var targetStream = System.IO.File.Create(saveToPath))
                    {
                        await section.Body.CopyToAsync(targetStream);
                    }

                    return Ok();
                }

                section = await reader.ReadNextSectionAsync();
            }

            return BadRequest("No files data in the request.");
        }
    }
}
```

I tested both methods using Postman. Both use `form-data` and an entry of type `file`. The only difference is that the `model binding` method requires that the entry to be named `files`. Consider that one methods is using **model binding or model validation** and another one is using **no-argument action** technique.