为啥 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用?

Posted

技术标签:

【中文标题】为啥 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用?【英文标题】:Why is Asp.Net Core Kestrel server returns 404 to Ngrok and Controller is never gets called?为什么 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用? 【发布时间】:2021-03-07 16:57:00 【问题描述】:

几天来,我正在尝试运行一个简单的 asp.net 核心应用程序,并为 Telegram bot 设置 webhook。它在 Mac 上运行,带有 Kestrel 服务器,Ngrok 在其上用于将 https 代理到 webhook。目前它向 Ngrok 返回 404,我在控制台中也看到 404。任何帮助表示赞赏。 我尝试了这条线的各种修改 ./ngrok http http://localhost:5000 -host-header=localhost:5000

我是 Asp.Net Core 的初学者。这是我应用的核心部分:

[Route("/")]
[ApiController]
public class UpdateController : ControllerBase

    [HttpPost]
    public async Task<OkResult> Post([FromBody]Update update)

这个永远不会被调用。 这是我的 Program.cs

public class Program

    public static void Main(string[] args)
    
        BuildWebHost(args).Run();
    

    private static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .Build();

Startup.cs

public class Startup

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        
        
        Bot.GetBotClientAsync().Wait();
    

Bot.cs

public static class Bot

    private static TelegramBotClient botClient;
    private static List<Command> commandsList;

    public static IReadOnlyList<Command> Commands => commandsList.AsReadOnly();

    public static async Task<TelegramBotClient> GetBotClientAsync()
    
        if (botClient != null)
        
            return botClient;
        

        commandsList = new List<Command>
        
            new StartCommand()
        ;

        botClient = new TelegramBotClient(AppSettings.Token);
        await botClient.SetWebhookAsync(AppSettings.NGrokUrl);
        return botClient;
    

设置 webhook 工作正常,Ngrok 接收请求,但来自 Kestrel 的答案始终是 404,并且永远不会调用 Post 方法。

控制台输出示例:

dbug: Microsoft.AspNetCore.Hosting.Diagnostics[3]
      Hosting starting
dbug: Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer[2]
      Failed to locate the development https certificate at '(null)'.
dbug: Microsoft.AspNetCore.Hosting.Diagnostics[4]
      Hosting started
dbug: Microsoft.AspNetCore.Hosting.Diagnostics[0]
      Loaded hosting startup assembly eBot
Hosting environment: Development
Content root path: /Users/yuriibabii/Projects/eBot/eBot
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[6]
      Connection id "0HM4GMVPJLPSF" received FIN.
dbug: Microsoft.AspNetCore.Server.Kestrel[39]
      Connection id "0HM4GMVPJLPSF" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
      Connection id "0HM4GMVPJLPSF" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
      Connection id "0HM4GMVPJLPSF" sending FIN because: "The client closed the connection."
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
      Connection id "0HM4GMVPJLPSF" disconnecting.
dbug: Microsoft.AspNetCore.Server.Kestrel[2]
      Connection id "0HM4GMVPJLPSF" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel[39]
      Connection id "0HM4GMVPJLPSG" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
      Connection id "0HM4GMVPJLPSG" started.
dbug: Microsoft.AspNetCore.Server.Kestrel[39]
      Connection id "0HM4GMVPJLPSH" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
      Connection id "0HM4GMVPJLPSH" started.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/ application/json 375
dbug: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[0]
      Wildcard detected, all requests with hosts will be allowed.
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSH" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 45.4537ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000001": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000001": done reading request body.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/  
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSG" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 9.3331ms 404 
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/ application/json 375
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSH" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 10.7676ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000002": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000002": done reading request body.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/ application/json 375
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSH" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 8.5738ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000003": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000003": done reading request body.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/ application/json 375
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSH" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 8.8111ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000004": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000004": done reading request body.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/ application/json 375
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
      All hosts are allowed.
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
      Connection id "0HM4GMVPJLPSH" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 9.6591ms 404 
dbug: Microsoft.AspNetCore.Server.Kestrel[25]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000005": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HM4GMVPJLPSH", Request id "0HM4GMVPJLPSH:00000005": done reading request body.

【问题讨论】:

【参考方案1】:

您是否发布了所有的 Startup 课程? 我没有看到任何必须有 services.AddMvc().AddMvcOptions() 行的 ConfigureServices 方法,也没有在 Configure 方法中看到 app.UseMvc() 行。

我不太确定,但我一直认为您需要这两行来启用控制器。

尝试以这种方式更改您的 Startup 类:

public class Startup

    public void ConfigureServices(IServiceCollection services)
    
        services.AddMvc().AddMvcOptions();
        services.AddControllersWithViews();
    


    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        
        
        app.UseRouting();
        app.UseMvc();

        Bot.GetBotClientAsync().Wait();
    

【讨论】:

它确实奏效了!谢谢你。但是我不得不在代码中添加几行,因此我发布了一个新答案。【参考方案2】:

对@PiGi78 的答案进行了一些修改,它确实有效。这是最终的解决方案:

public class Startup

    public void ConfigureServices(IServiceCollection services)
    
        services.AddMvc().AddMvcOptions(ApplyMvcOptions);
        services.AddControllersWithViews();
        services.AddControllers().AddNewtonsoftJson();
    

    private void ApplyMvcOptions(MvcOptions options)
    
        options.EnableEndpointRouting = false;
    

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        
        
        app.UseRouting();
        app.UseMvc();
        
        Bot.GetBotClientAsync().Wait();
    

@PiGi78 非常感谢!

【讨论】:

以上是关于为啥 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解

请求内容意外结束 Kestrel ASP.NET Core

ASP.NET Core Kestrel 随机404错误

为 HTTPS 配置 ASP.NET Core 2.0 Kestrel

在 Kestrel 上为 ASP.NET Core 上的两个不同端点发布两个不同的端点

用于 Asp.Net Core 的 Kestrel 网络服务器 - 是不是在一段时间后回收/重新加载