ASP.NET Core API - 在 Azure 应用服务上获取 404,但在本地主机上运行正常

Bri*_*lig 9 azure asp.net-core-webapi

我有一个托管在 Azure 应用服务中的 ASP.NET Core 2.1 应用。在本地执行时,我可以访问控制器。但是当我托管在 Azure 应用程序中时,我收到 404。以下是重现的最少步骤。

在 Visual Studio 2017 中添加一个新项目。选择 ASP.NET Core Web 应用程序。选择 ASP.NET Core 2.1,API 项目模板,无身份验证,配置为 HTTPS。将新应用作为自托管(不使用 IIS)运行。浏览到 https://localhost:5001/api/values。我得到了预期的响应(尽管命令行上有一个关于无法对 HTTPS 连接进行身份验证的异常)。

右键单击项目并选择发布。选择以创建新的应用服务。我选择了我现有的订阅、托管计划和资源组。我保留了默认的应用程序名称。创建应用程序。

浏览到 url https://app_name.azurewebsites.net,我看到了默认页面。浏览到https://appname.azurewebsites.net/api/values,我得到一个 404。

我确定我错过了一些非常愚蠢的东西,但我就是想不通。

Stu*_*tLC 13

if (env.IsDevelopment())造成不同行为的一个可能原因是中的标准 分支,它将根据或环境变量Startup.cs -> Configure()的值而变化。这些将默认为生产ASPNETCORE_ENVIRONMENTDOTNET_ENVIRONMENT

就我而言,我Home完全删除了控制器,但无意中将app.UseExceptionHandler中间件留在了Startup.Configure指向默认值的位置Home/Error

因此,当我的应用程序部署到 Azure 时,发生了我在本地测试期间未收到的异常(例如 SQL 防火墙 IP 阻止问题),这意味着任何到错误页面的重定向都会导致 404。

if (env.IsDevelopment())
   ... << Local environment (ASPNETCORE_ENVIRONMENT = 'Development')
else
{
    app.UseExceptionHandler("/Home/Error"); << Watch for this
    ...
}
Run Code Online (Sandbox Code Playgroud)


tom*_*dox 8

与 @StuartLC 的答案类似,对于 Visual Studio 的 .NET Core Web API 模板,还有另一个仅在开发时使用的选项需要警惕:

我花了一个非常令人沮丧的小时,愚蠢地期望当我在浏览器中导航到新部署的 Azure WebApp 时,它会向我显示 API 的 Swagger 页面。相反,我只是收到了 404。我应该做的是使用 Postman 或其他任何东西来检查。

当我检查代码时,我才意识到 Swagger UI 仅在开发时默认连接到模板中:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication6 v1"));
    }
Run Code Online (Sandbox Code Playgroud)


小智 7

我能够重现错误,以下解决方案对我有用。如果您之前没有尝试过,请尝试此操作。

  1. 在将应用程序发布到 Azure 之前,确保将配置设置为发布模式。
  2. 在 ValuesController 中的 GET 方法之上添加 [Route("/")]属性,如下所示。

    [Route("/")]
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return "value";
    }
    
    Run Code Online (Sandbox Code Playgroud)

基本上,任何没有路由属性的控制器方法都使用基于约定的路由。

当您使用 [Route] 属性时,您定义了属性路由,因此该操作/控制器不使用常规路由。

作为一种选择,您可以使用属性路由可以与继承相结合的事实。在整个控制器上设置 Route 属性,这将用作路由前缀(与 WebApi 中的 [RoutePrefix] 属性相同):

[Route("api/[controller]")]
public class ValuesController: ControllerBase
{

}
Run Code Online (Sandbox Code Playgroud)