ASP.NET 从 WebHostBuilder (Pre-.NET 3.0) 迁移到 IHostBuilder + ConfigureWebHostDefaults (Post-.NET 3.0) 导致 API 返回 404 错误
ASP.NET Migration from WebHostBuilder (Pre-.NET 3.0) to IHostBuilder + ConfigureWebHostDefaults (Post-.NET 3.0) causes API returning 404 error
我们有一个项目从 .NET Core 2.2 开始,最近迁移到 .NET 6。在这个项目中,我们使用了 WebHostBuilder,因为我们使用了 Rest API 和托管服务的组合,我们决定重新- 将我们的主机实现为 .NET Core 3 中引入的新通用主机。
但是在将我们的 WebHost 重新实现为通用主机 + WebHostDefaults 方法组合之后,我们所有的 API 调用开始出现 return 404 not found 错误消息,就好像控制器没有 found/mapped 正确以及我关于如何修复它的想法 运行。
我们的 HostBuilder 实现:
var host = builder
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults((webBuilder) =>
webBuilder.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseWebHostConfiguration(ComponentName, commandLineArguments, out configuration)
.UseStartup(webHost => StartupClassFactory()))
.Build();
启动时配置服务的实现Class:
private void ConfigureServices(IServiceCollection services)
{
//Configure other non-API services
services
.AddMvc(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson(options => JsonSettings.SetSettings(options.SerializerSettings));
}
在启动时配置实现 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();
}
控制器片段:
//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);
}
}
}
在调试和尝试 /GetAllApiRoute API 调用时我发现,请求通过所有中间件并在 UseMvc 上停止,它只抛出 404 Not Found 响应所以注册 Controller 或将请求路由到 Controller 似乎有问题。
方法 ConfigurateServices 和 Configurate 与它们在 .NET 2.2 上的实现相同,并且一切正常。因此,我猜想从 .NET 2.2 到 .NET 6,WebHost 配置一定发生了一些变化,这使得这段代码无法正常工作,但我无法弄清楚是什么,而且我在网上也没有找到任何对我有帮助的东西。
这是我试过但没有帮助的方法:
- 将 AddMvc() 替换为 AddControllers() 并将 UseMvc() 替换为 UseEndpoints(endpoints => endpoints.MapControllers())
- 省略 Startup class 并直接从构建器调用 Configure 和 ConfigureServices
任何帮助将不胜感激:)
对我来说,问题是我的 HostBuilder
与控制器在不同的程序集(库项目)中,因为它在多个不同的项目中使用。显然加载控制器的逻辑一定已经改变,它只在 HostBuilder
所在的程序集中寻找控制器。所以将 AddApplicationPart
添加到 ConfigureServices
解决了我的问题,现在一切正常。
解决方案代码:
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
我们有一个项目从 .NET Core 2.2 开始,最近迁移到 .NET 6。在这个项目中,我们使用了 WebHostBuilder,因为我们使用了 Rest API 和托管服务的组合,我们决定重新- 将我们的主机实现为 .NET Core 3 中引入的新通用主机。
但是在将我们的 WebHost 重新实现为通用主机 + WebHostDefaults 方法组合之后,我们所有的 API 调用开始出现 return 404 not found 错误消息,就好像控制器没有 found/mapped 正确以及我关于如何修复它的想法 运行。
我们的 HostBuilder 实现:
var host = builder
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults((webBuilder) =>
webBuilder.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseWebHostConfiguration(ComponentName, commandLineArguments, out configuration)
.UseStartup(webHost => StartupClassFactory()))
.Build();
启动时配置服务的实现Class:
private void ConfigureServices(IServiceCollection services)
{
//Configure other non-API services
services
.AddMvc(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson(options => JsonSettings.SetSettings(options.SerializerSettings));
}
在启动时配置实现 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();
}
控制器片段:
//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);
}
}
}
在调试和尝试 /GetAllApiRoute API 调用时我发现,请求通过所有中间件并在 UseMvc 上停止,它只抛出 404 Not Found 响应所以注册 Controller 或将请求路由到 Controller 似乎有问题。
方法 ConfigurateServices 和 Configurate 与它们在 .NET 2.2 上的实现相同,并且一切正常。因此,我猜想从 .NET 2.2 到 .NET 6,WebHost 配置一定发生了一些变化,这使得这段代码无法正常工作,但我无法弄清楚是什么,而且我在网上也没有找到任何对我有帮助的东西。
这是我试过但没有帮助的方法:
- 将 AddMvc() 替换为 AddControllers() 并将 UseMvc() 替换为 UseEndpoints(endpoints => endpoints.MapControllers())
- 省略 Startup class 并直接从构建器调用 Configure 和 ConfigureServices
任何帮助将不胜感激:)
对我来说,问题是我的 HostBuilder
与控制器在不同的程序集(库项目)中,因为它在多个不同的项目中使用。显然加载控制器的逻辑一定已经改变,它只在 HostBuilder
所在的程序集中寻找控制器。所以将 AddApplicationPart
添加到 ConfigureServices
解决了我的问题,现在一切正常。
解决方案代码:
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