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)