[SOLVED] ASP.NET Migration from WebHostBuilder (Pre-.NET 3.0) to IHostBuilder + ConfigureWebHostDefaults (Post-.NET 3.0) causes API returning 404 error

Issue

We have a project that started on .NET Core 2.2 and recently was migrated to .NET 6. In this project we used WebHostBuilder because we used combination of Rest API and Hosted Services and we decided to re-implement our hosts to new Generic hosts that were introduced in .NET Core 3.

But after reimplementation of our WebHost to Generic Host + WebHostDefaults method combo all of our API calls started to return 404 not found error message as if Controllers were not found/mapped correctly and my ideas of how to fix it ran out.

Our HostBuilder implementation:

            var host = builder
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults((webBuilder) =>
            webBuilder.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
                      .UseWebHostConfiguration(ComponentName, commandLineArguments, out configuration)
                      .UseStartup(webHost => StartupClassFactory()))
            .Build();

ConfigureServices implementation in Startup Class:

        private void ConfigureServices(IServiceCollection services)
        {
            //Configure other non-API services

            services
                .AddMvc(options => options.EnableEndpointRouting = false)
                .AddNewtonsoftJson(options => JsonSettings.SetSettings(options.SerializerSettings));

        }

Configure implementation in Startup Class:

        protected override void Configure(
            IApplicationBuilder app,
            ILoggerFactory loggerFactory,
            IServiceProvider serviceProvider,
            IHostApplicationLifetime applicationLifetime)
        {
            //Database Migration Stuff here

            app.UseMiddleware<InquiryMetricLogHandlerMiddleware>();
            app.UseMiddleware<ExceptionHandlerMiddleware>();
            app.UseMiddleware<SeedingCheckMiddleware>();

            if (QueryLocking)
            {
                QueryLockingMiddlewareApplicator(app);
            }

            app.UseMvc();
        }

Controller snippet:

//Our Internal libraries
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace MyProject
{
    [ApiController]
    [Route(Routes.ApiRoute1 + "/{id:guid}/" + Routes.ApiRoute2)]
    public class CustomController : SqliteInquiryController<MyModel>
    {
        public TokensController(
            DI arg1,
            DI arg2,
            DI arg3)
            : base(arg1, arg2, arg3)
        {
            //Constructor stuff
        }
        
        [Route("/" + Routes.GetAllApiRoute), HttpGet, PaginationValidation]
        public override async Task<IActionResult> GetList()
        {
            //Build Database LINQ query
 
            return Ok(response);
        }
     }
}

When debugging and trying /GetAllApiRoute API call I found out, that requests go through all Middlewares and stop on UseMvc where it throws just 404 Not Found response so it seems like problem with registering of Controller or routing request to Controller.

Methods ConfigurateServices and Configurate have the same implementation as they had on .NET 2.2 and everything worked fine. So I guess something must have changed in WebHost configuration along the way from .NET 2.2 until .NET 6 which makes this code disfunctional but I can’t figure out what and I also didn’t find anything on the web what would help me.

Here is what I’ve tried but didn’t help:

  • Replacing AddMvc() for AddControllers() and UseMvc() for UseEndpoints(endpoints => endpoints.MapControllers())
  • Omit Startup class and call Configure and ConfigureServices directly from the builder

Any help would be highly appreciated 🙂

Solution

For me the problem was that my HostBuilder was in different assembly (Library Project) than Controllers as it was used in multiple different projects. And apparently the logic of loading Controllers must have changed and it was looking for Controllers only in Assembly where HostBuilder was located. So adding AddApplicationPart into ConfigureServices fixed my problem and everything works fine now.

Solution Code:

services
       .AddControllers()
       .AddNewtonsoftJson(options => JsonSettings.SetSettings(options.SerializerSettings))
       .AddApplicationPart(Assembly.GetEntryAssembly()); //Adding this will look for Controllers in your Entry Point assembly where most likely your Controllers are

Answered By – Scourrge

Answer Checked By – Katrina (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *