Azure Web API giving a 404 when deployed but works locally - azure

We have a .NET Core Web API deployed as an Azure Web App. All endpoint work locally, however, once deployed, we have one controller that is gives us a 404 for all endpoint we hit within it.
We have checked and triple checked that the url we are calling is correct & from what we can tell, there is nothing different about this controller relative to the others in our application.
This is our BinController that is giving us 404's:
namespace API.Controllers
{
[Route("api/[controller]")]
[Authorize]
[ApiController]
public class BinController : ControllerBase
{
private readonly IBinRepository _binRepo;
private readonly ILogger _logger;
public BinController(IBinRepository binRepo, ILogger<BinController> logger)
{
_binRepo = binRepo;
_logger = logger;
}
[HttpGet("{locationId}/{binId}")]
public async Task<IActionResult> CheckBinExists(int locationId, string binId)
{
try
{
bool result = await _binRepo.CheckBinExists(locationId, binId);
return Ok(result);
}
catch (Exception e)
{
return StatusCode(StatusCodes.Status500InternalServerError, e.Message);
}
}
[HttpGet("findAll/{locationId}/{itemId}")]
public async Task<IActionResult> FindAllBinsWithItem(int locationId, string itemId)
{
try
{
var result = await _binRepo.FindAllBinsWithItem(locationId, itemId);
return Ok(result);
}
catch (Exception e)
{
_logger.LogError(e.Message);
return StatusCode(StatusCodes.Status500InternalServerError, e.Message);
}
}
[HttpGet("contents/{locationId}/{bin}")]
public async Task<IActionResult> GetBinContents(int locationId, string bin)
{
try
{
List<BatchLine> contents = await _binRepo.GetBinContents(locationId, bin);
return Ok(contents);
}
catch (Exception e)
{
_logger.LogError(e.Message);
return StatusCode(StatusCodes.Status500InternalServerError, e.Message);
}
}
}
}
We are calling https://ourapiname.azurewebsites.net/api/Bin/1234/TestBin.
To Summarize:
All endpoints work locally
All controllers work when deployed except for one
We have multiple other controllers in our application with similar if not the same setup, but this one is returning a 404 when deployed
We saw these similar posts, but they did not resolve this issue:
Web API interface works locally but gets 404 after deployed to Azure Website
Web api call works locally but not on Azure
I wish I could provide more insight, but we are really at a loss for what could be going on here. Any ideas would be greatly appreciated.

You can deploy your web project with Self-Contained mode, then find the project_name.exe and double-click it. Test it in your local, and your test url should be https://localhost:5001/api/Bin/1234/TestBin.
If you can run it works well in your local, the second step you should to create a new webapp, then deploy it as usual. We just rult out the some specifical reason in your original webapp.(like: deploy failed)
If it still not work, my suggestion is you can manually drag and drop the publish file to the kudu site of the azure webapp.
The steps above should be useful to you, but I think the easiest way is to go to the kudu site to get the dll file, and then decompile it, so that the root cause of the problem can be found.

This does not make any sense, but I simply changed the name of the Controller from "BinController" to "BinsController" and now it works...
Must not be able to name a controller "Bin".

Related

API asp.net core : I have been trying to execute the Get method but i get the error code 500, how can I fix this

THIS IS MY CODE
This code is a Device controller that is one of the controllers I have created..
// GET: api/Devices
[HttpGet]
public async Task<ActionResult<IEnumerable<Device>>> GetDevice()
{
return await _context.Device.ToListAsync();
}
// GET: api/Devices/5
[HttpGet("{id}")]
public async Task<ActionResult<Device>> GetDevice(Guid id)
{
var device = await _context.Device.FindAsync(id);
if (device == null)
{
return NotFound();
}
return device;
}
I have deployed ASP.NET Core Web API and able to access the Get request, follow the below steps
Create an ASP.NET Core API in Visual studio
Below is the file structure
ProductsController.cs
Use post method in ProductController.cs use the below
[HttpGet]
public ActionResult<IEnumerable<Product>> GetAll() => Ok(_productService.GetAll());
[HttpGet("{id}")]
public ActionResult<Product> Get(Guid id) => Ok(_productService.Get(id));
Deployed the Web-app to Azure app service from visual studio
I have tried the Get request and got the below output
Now Goto Get ID and use the copied id there as click on send
After that you will get the value with the help of ID as below

.NET Core API will not work on Azure App Service-The resource you are looking for has been removed,had its name changed,or is temporarily unavailable

I've deployed my API to an Azure App Service and get the error:
The resource you are looking for has been removed,had its name changed,or is temporarily unavailable.
any time I try to hit the endpoint of the only current operation in the API. All of the files have deployed correctly in the wwwroot folder and if I enter url/filename where url is the base url and filename is any of the files in the folder, I am able to download the file. The API works when run locally, hitting the operation returns the expected json result.
Running a trace gives the rather generic result:
System.NullReferenceException 2
Object reference not set to an instance of an object.
Stack Trace 1
mscorlib!System.Diagnostics.Tracing.EventSource.SendCommand
mscorlib!System.Diagnostics.Tracing.EventSource+OverideEventProvider.OnControllerCommand
mscorlib!System.Diagnostics.Tracing.EventProvider.EtwEnableCallBack
mscorlib!dynamicClass.IL_STUB_ReversePInvoke
The routes are configured correctly (in that it works locally) - the error implies that a related file is missing, however checking the folder in Kudu shows the files match the contents of the bin folder. Any ideas on what is going wrong here? Or how to determine what the missing resource is? Thanks for reading.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddLogging(logging =>
{
logging.AddConsole();
logging.AddDebug();
});
services.AddDbContext<hidden>(options => options.UseSqlServer(Configuration.GetConnectionString("hidden")));
services.AddScoped<DbContext, hidden>();
services.AddScoped(typeof(IQuery<>), typeof(NoTrackingQuery<>));
services.AddScoped(typeof(IQuery<,>), typeof(NoTrackingQuery<,>));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Hidden", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Expose logging where DI cannot be used
var loggerFactory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
LogManager.SetLogger(loggerFactory);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Hidden v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
[ApiController]
[Route("[controller]")]
public class WidgetController : ControllerBase
{
private readonly IQuery<Category> _categories;
public WidgetController(IQuery<Widget> widgets)
{
_widgets = widgets;
}
[HttpGet]
public IEnumerable<Widget> Get()
{
return _widgets.QueryAll();
}
}
When you can run a solution locally, and not able to run it on Cloud, it means that you have misconfigured something.
Looking at the error message I suspect that the settings for Logging are not in place. Make sure that you put all required/consumed settings in Application Settings or Connection Strings.
Thanks singhh-msft. You were right and this was caused by using the incorrect publish task in the build pipeline. Updated to use dotnet Azure CLI publish command and the issue is resolved.

How can I view console or trace output in an azure app service? Console.WriteLine or Trace.TraceError

I thought this would be simple but after several hours have realized that it is not. I deployed an "App Service" to Azure that is a C# .Net Core.
I am trying to add some crude monitoring of by app by using Console.WriteLine("my message") or Trace.TraceError("my message") but I can't find that output anywhere in Azure.
I tried enabling Application Insights but didn't find the output there either.
I just want the simplest way to get a little idea that a line of code in my app is getting hit. What is that simplest way?
Things I have tried:
1) I went in to the console in Azure and browsed to every file that might have this sort of output but did not find any. Certainly nothing in any of the files and folders under LogFiles.
2) I DID go to "App Service Logs" and enabled "Application Logging (Filesystem)".
3) I also enabled "Detailed error messages" in "App Service Logs".
4) I tried "Diagnostic settings (preview)" but could not find the output there.
5) I watch the "Log Stream" for Application Logs but nothing shows up there
6) Under "Logs" I just have this message: "We didn’t find any logs"
7) Neither "metrics" nor "Alerts" has this log output
I am beginning to suspect this is not support in Azure. Do I need to add a logging framework like serilog just to one time add a statement to may app like "You hit line 20"? I really just want something quick and dirty, but after spending a few hours on this the "quick" part of it isn't happening.
What I did was just to enable the App Service Logs in the Azure Portal.
Specifically I turned on the "Application Logging (Filesystem)" at the "Verbose" Level and then I selected "File System" in the "Web server logging" option
Then you can use the "Log stream" in the left bar to display the application logs.
In your code you just have to call
System.Diagnostics.Trace.TraceInformation("My message!")
Or
System.Diagnostics.Trace.WriteLine("My message!")
And that's it!
Here I include some screenshots:
I finally figured it out myself. I needed to add configuring AzureFileLoggerOptions. Without those options, nothing showed up in the Azure output.
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
})
)
In summary, for .Net Core 3.1, to get your messages to show up in the "Log Stream", you need to enable "Application Logging" in the "App Service Logs" section of Azure. In your code you need to reference:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.AzureAppServices;
Also, in my case, I am using Blazor/SignalR and don't have an MVC Controller, so I couldn't figure out how to access the Logging framework in my class. I am sure there is a better way, but by exposing the ILogger as in the code below I was able to reference it from anywhere within my code base.
I have a static method I call to write to the log (console when I am actively debugging on my pc, or Azure "Log Stream" when running in Azure:
public static void WriteToLog(string message)
{
Program.Logger.LogError(message);
}
Code in my Program.cs looks like this:
public class Program
{
public static ILogger Logger;
public static void Main(string[] args)
{
//CreateHostBuilder(args).Build().Run();
var host = CreateHostBuilder(args).Build();
var LoggerF = LoggerFactory.Create(builder =>
{
builder.AddFilter("BlazorDiceRoller", LogLevel.Warning)
.AddConsole().AddAzureWebAppDiagnostics()
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning);
});
Logger = LoggerF.CreateLogger<Program>();
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
}).Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
})
)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
You can open Kudu and view Console.WritLine output. Open it from portal or:
https://your_app_name_on_azure.scm.azurewebsites.net/api/logstream
Don't forget to enable logs in azure:
Yes, this(console or trace output) is not supported in .NET core only. You should take use of ILogger as per steps below.
In Startup.cs -> Configure method, re-write Configure method like below:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//your other code
//add the following 2 lines of code.
loggerFactory.AddConsole();
loggerFactory.AddDebug();
app.UseStaticFiles();
//your other code
}
Then in HomeController.cs(for example), add the following code:
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<HomeController>();
}
public IActionResult Index()
{
_logger.LogInformation("this is a information from ILogger...");
return View();
}
//other code
}
Please let me know if you still have more issues.
Try to use the namespace System.Diagnostics.Trace to register info about diagnostic
eg:
System.Diagnostics.Trace.TraceError("If you're seeing this, something bad happened");
By Default, ASP.NET Core use the provider for logs this namespace: Microsoft.Extensions.Logging.AzureAppServices.

MobileServiceInvalidOperationException is thrown on Xamarin.WindowsPhone 8.1 project

I'm trying to use Azure Mobile Services and Xamarin. I follow all instuctions of official tutorial, created Azure backend for application and downloaded sample quick-start app for Xamarin.Forms from Azure.
There is code in TodoItemManager.cs:
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync(bool syncItems = false)
{
try
{
IEnumerable<TodoItem> items = await todoTable
.Where(todoItem => !todoItem.Done)
.ToEnumerableAsync();
return new ObservableCollection<TodoItem>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
}
return null;
}
And I got MobileServiceInvalidOperationException with message "Invalid sync operation: The request could not be completed. (Not Found)".
I have tested Azure Backend on UWP App and it works fine. So looks like there is problem in WP8.1 project. Can anybody help with this exception?
So.. I forgot to enable internet connection on my Windows Phone

Custom maintenance mode module does not work on Azure Web Role

I've created and registered custom http module to show maintenance message to user after administrator turns on maintenance mode via configuration change.
When I pass request for html it should return custom html loaded from file, but it returns message: "The service is unavailable." I can't find that string in my entire solution. Custom log message from custom maintenance module is written to log4net logs.
... INFO DdiPlusWeb.Common.MaintenanceResponder - Maintenance mode is on. Request rejected. RequestUrl=...
Seems something is miss configured in IIS on Azure. Something intercepts my 503 response. How to fix it?
Module code
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
if (AppConfig.Azure.IsMaintenance)
{
MaintenanceResponder responder = new MaintenanceResponder(context, MaintenaceHtmlFileName);
responder.Respond();
}
}
Interesting part of responder code.
private void SetMaintenanceResponse(string message = null)
{
_context.Response.Clear();
_context.Response.StatusCode = 503;
_context.Response.StatusDescription = "Maintenance";
if (string.IsNullOrEmpty(message))
{
_context.Response.Write("503, Site is under maintenance. Please try again a bit later.");
}
else
{
_context.Response.Write(message);
}
_context.Response.Flush();
_context.Response.End();
}
EDIT: I lied. Sorry. Maintenance module returns the same message for requests that expect json or html.
This answer led me to the solution.
I've added another line to SetMaintenanceResponse method.
_context.Response.TrySkipIisCustomErrors = true;
It works now. Here is more about what it exactly means.

Resources