Reputation: 648
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.
Upvotes: 20
Views: 12205
Reputation: 30543
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"));
}
Upvotes: 9
Reputation: 107387
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
...
}
Upvotes: 13
Reputation: 973
I was able to reproduce the error and below solution worked for me. Try this if you haven't tried earlier.
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
{
}
Upvotes: 8