20

I have an ASP.NET Core 2.1 app that I've hosted in an Azure app service. When executed locally I'm able to access the controller. But when I host in an Azure app I receive a 404. Here are the minimal steps to reproduce.

In Visual Studio 2017 add a new project. Select ASP.NET Core Web Application. Select ASP.NET Core 2.1, API project template, no authentication, configure for HTTPS. Run the new app as a self hosted (not using IIS). Browse to https://localhost:5001/api/values. I get the expected response (although there is an exception on the command line about failure to authenticate HTTPS connection).

Right click the project and select publish. Select to create a new app service. I selected my existing subscription, hosting plan, and resource group. I left the default app name. Create the app.

Browse to the url https://app_name.azurewebsites.net and I see the default page. Browse to https://appname.azurewebsites.net/api/values and I get a 404.

I'm sure I'm missing something quite stupid, but I just can't figure it out.

4
  • 1
    It's hard to tell without any more data. Do you have diagnostics or Application Insights enabled so you can share more information? Commented Apr 12, 2019 at 20:27
  • Yes, application insights is enabled. Commented Apr 12, 2019 at 20:32
  • 2
    Not reproduce with your steps ,could you please provide more details ? Commented Apr 15, 2019 at 6:57
  • I've followed the steps listed above and I've reproduced it again. I made sure to create a new hosting plan and resource group. I don't know what else to do. Commented Apr 15, 2019 at 17:08

3 Answers 3

13

One possible cause of differing behaviour is the standard if (env.IsDevelopment()) branch in Startup.cs -> Configure(), which will change depending on the value of the ASPNETCORE_ENVIRONMENT or DOTNET_ENVIRONMENT env vars. These will default to production

In my case, I had removed the Home controller entirely, but inadvertently left the app.UseExceptionHandler middleware in Startup.Configure pointed at the default Home/Error.

So when my app was deployed to Azure, an exception happened which I didn't receive during local testing (e.g. SQL Firewall IP blocking issue), and this meant that any redirection to the error page resulted in a 404.

if (env.IsDevelopment())
   ... << Local environment (ASPNETCORE_ENVIRONMENT = 'Development')
else
{
    app.UseExceptionHandler("/Home/Error"); << Watch for this
    ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

This got me on the right track. Turns out my entire Swagger configuration was inside the "if (env.IsDevelopment())" brackets. I dont know if I was unfocused while setting up the application, or if I used a weird template, but I am so glad this was the problem. With just a 404 and the lack of any error messages, I started to lose faith. But as always, it was on me....
Continuing from my last comment. The "ASP.NET Core Web Api" template in Visual Studio (at least the one I use) adds this as default inside the if(env.IsDevelopment()) condition. However, now that my head is more clear, I can easily see the benefits of exposing our API documentation only to our developers, and not the entire world :-D The template is not weird, you just have to place app.UseSwagger() and app.UseSwaggerUI() correctly, based on what you want to achieve.
9

I was able to reproduce the error and below solution worked for me. Try this if you haven't tried earlier.

  1. Ensure the configuration is set to Release Mode before publishing the app to Azure.
  2. Add [Route("/")] attribute on top of your GET method in ValuesController like below.

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

Basically, Any controller methods that do not have a route attribute use convention-based routing.

When you use [Route] attribute, you define attribute routing and so conventional routing is not used for that action/controller.

As an option, you can use the fact, that attribute routes can be combined with inheritance. Set a Route attribute on the entire controller and this will work as route prefix (the same behavior as [RoutePrefix] attribute in WebApi):

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

}

4 Comments

Thank you for the help. This suddenly started working. I followed the exact same steps multiple times, and now it is working. It's very strange.
Oops, I forgot to mention I upgraded Visual Studio 2017 from 15.9.10 to 15.9.11.
I put [Route("/")] in the Get action, but is the only action that works
its weird..its not working for some app service but when deployed to other app service, it works..is there other things need to consider with this error? :(
9

Similarly to the @StuartLC's answer, there's another development-time-only option to be wary of with Visual Studio's .NET Core Web API template:

I spent a very frustrating hour foolishly expecting a newly deployed Azure WebApp to show me the Swagger page for my API when I navigated to it in the browser. Instead I was just getting a 404. What I should have done was used Postman or whatever to check.

Only when I checked the code did I realise that the Swagger UI is only wired in at development time by default in the template:

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"));
    }

1 Comment

Thanks! I recall swagger being scaffolded in to my new Web API project and this made me check on that. Sure enough, it's under the dev config. This makes sense because it exposes good info to anyone who may have less than productive intentions. Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.