Uploading a File in ASP.NET Core with Razor Pages

In this tutorial I’m going to show how simple it is to create an upload file page using ASP.NET core and Razor pages. The codebase I’m working on is using Razor pages so I’m doing this way even though I know most people are probably using MVC, but there should be minimal difference between doing this in Razor and MVC. Hope you can all handle that. So let’s get started!

First, create a new ASP.NET webapp project:

> dotnet new webapp -n AspDotNetCoreUploadFile

To make this example as short as possible, I’m going to modify the Index.cshtml page (located in the Pages directory) to contain the HTML code that used to upload the file:

@page
@model IndexModel
@{
    ViewData["Title"] = "Upload File";
}

<div class="text-center">
    <h1>Upload File</h1>
</div>

<form method="post" enctype="multipart/form-data">
    <input type="file" name="uploadedFile" />
    <button type="submit" style="">Upload</button>
</form>

As you can see, this is just a simple form that submits a file as a POST message to the page. The code behind the Razor page is also very simple, as the framework takes care of most of the complex stuff:

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace AspDotNetCoreUploadFile.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
        private readonly IHostEnvironment _environment;

        public IndexModel(ILogger<IndexModel> logger, IHostEnvironment environment)
        {
            _logger = logger;
            _environment = environment;
        }

        public void OnGet()
        {
        }

        public async Task OnPostAsync(IFormFile uploadedFile)
        {
            if (uploadedFile == null || uploadedFile.Length == 0)
            {
                return;
            }

            _logger.LogInformation($"Uploading {uploadedFile.FileName}.");
            string targetFileName = $"{_environment.ContentRootPath}/{uploadedFile.FileName}";
            using (var stream = new FileStream(targetFileName, FileMode.Create))
            {
                await uploadedFile.CopyToAsync(stream);
            }
        }
    }
}

A couple of things should be noted here. First, the file is uploaded to the root directory of the application, which is different from the root directory of the static web files for the application (which is usually wwwroot), so if you plan on fetching the uploaded files later from a web page, make sure they are located under the wwwroot directory or another path that can be accessed externally. Second, I’m uploading the file to a local directory in the production server, which is definitely NOT what you want to do in a real-world scenario, where you would probably put the file in a remote file server or cloud storage.

To test how the app works, execute:

> dotnet run
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001       
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000        
...

And navigate to the URL that is shown.

As always, the code for this tutorial is located in my GitHub repo. Note that I’ve removed a couple more (unused) files from the project to keep it as clean as possible.

And that is all for today. Until next time, happy coding!