Search code examples
c#asp.net-coreblazor.net-8.0blazor-webapp

Blazor web app ASP.NET Core 8.0 controller not finding route


How to use controllers in a Blazor web app? My route is not being found.

local host page can't be found

file folder structure

I have AddControllers and MapControllers in my program.cs.

I want to be able to add a simple route to this controller so I can test how to download files, but I am unable to route to this controller when I type into the url.

I am not sure what I am missing or how to get the controller to be called. I have done the map and add controllers which has not brought anything.

using Microsoft.AspNetCore.Mvc;
using System.IO.Compression;

namespace SecureFileShare.Controllers
{
    public class HomeController : ControllerBase
    {
        [ApiController]
        [Route("api/[controller]")]
        public class FilesController : ControllerBase
        {
            private readonly IWebHostEnvironment _hostEnvironment;

            public FilesController(IWebHostEnvironment hostEnvironment)
            {
                _hostEnvironment = hostEnvironment;
            }

            [HttpGet]
            [Route("download-zip")]
            public IActionResult DownloadFiles()
            {
                try
                {
                    var folderPath = Path.Combine(_hostEnvironment.ContentRootPath, "FilesToDownload");

                    // Ensure the folder exists
                    if (!Directory.Exists(folderPath))
                        return NotFound("Folder not found.");

                    // Get a list of files in the folder
                    var files = Directory.GetFiles(folderPath);

                    if (files.Length == 0)
                        return NotFound("No files found to download.");

                    // Create a temporary memory stream to hold the zip archive
                    using (var memoryStream = new MemoryStream())
                    {
                        // Create a new zip archive
                        using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                        {
                            foreach (var file in files)
                            {
                                var fileInfo = new FileInfo(file);

                                // Create a new entry in the zip archive for each file
                                var entry = zipArchive.CreateEntry(fileInfo.Name);

                                // Write the file contents into the entry
                                using (var entryStream = entry.Open())
                                using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
                                {
                                    fileStream.CopyTo(entryStream);
                                }
                            }
                        }

                        memoryStream.Seek(0, SeekOrigin.Begin);

                        // Return the zip file as a byte array
                        return File(memoryStream.ToArray(), "application/zip", "files.zip");
                    }
                }
                catch (Exception ex)
                {
                    return StatusCode(500, $"An error occurred: {ex.Message}");
                }
            }
        }
    }
}
using SecureFileShare.Client.Pages;
using SecureFileShare.Components;

using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SecureFileShare.Services;

var builder = WebApplication.CreateBuilder(args);


// For windows authentication 
// ---------------------
// First add nuget package Microsoft.AspNetCore.Authentication.Negotiat
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

// Inject IHttpContextAccessor
builder.Services.AddHttpContextAccessor();

// Injects
builder.Services.AddScoped<UserService>();
builder.Services.TryAddEnumerable(
    ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());


builder.Services.AddControllers();  ///I ADDED CONTROLLER HERE

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseAntiforgery();

///
app.UseAuthentication();
app.UseAuthorization();
///

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(SecureFileShare.Client._Imports).Assembly);

app.MapControllers();   ///I MAPPED CONTROLLER HERE

app.Run();

Solution

  • I am not sure what I am missing or how to get the controller to be called. I have done the map and add controllers which has not brought anything.

    Based on your shared code snippet and description ,the issue lies in the nesting of your FilesController class. Because, you currently have FilesController nested within HomeController. This is incorrect because controllers should be separate classes.

    I have reproduced the issue accordingly as you can see below:

    enter image description here

    enter image description here

    In order to fix this issue, your fileController should have its own class instead of being nested within HomeController class.

    Just create another controller class with FilesController itself. You can do as following:

    [ApiController]
    [Route("api/[controller]")]
    public class FilesController : ControllerBase
    {
        private readonly IWebHostEnvironment _hostEnvironment;
    
        public FilesController(IWebHostEnvironment hostEnvironment)
        {
            _hostEnvironment = hostEnvironment;
        }
    
        [HttpGet]
        [Route("download-zip")]
        public IActionResult DownloadFiles()
        {
            
        }
    }
    

    Output:

    The request has been hit the download-zip action as expected.

    enter image description here

    enter image description here

    enter image description here

    Note: Please refer to this official document. Also routing in web API.