We got a hazardous deployment on Azure: in every 4-5th release the pipeline timed out after 60 minutes of waiting for Azure. First we suspected Azure services, as the script was hanging on their API call, but there was no outage report. Tried to investigate other deployments when this one failed, but every other worked just fine. Searching Microsoft’s wiki gave the answer:
One of our App Services run out of memory couple of times so we decided to upgrade them to a higher tier, P3mv3 was our target. We checked the availability on Azure, everything seemed to be OK, but the tier wasn’t listed under “Scale up” blade of the App Service Plan:
We rechecked the VM’s availability using CLI, it gave the same result: the tier should be shown.
Decided to give a try to the Azure CLI and upgrade through it, but no luck:
Finally we contacted Azure support to help us out, but their answer wasn’t promising: our Resource Group is too old and doesn’t support the needed VM. Meaning we had to recreate our Resource Group to be able to use higher tier App Services.
With the new Resource Group we were able to scale out.
Let’s say you want to upgrade your App Service Plan to a higher tier but first you want to check which regions support the given VM size. You can click through the Azure website for that information or you can use the Azure CLI.
When we run a command like python --version from CLI, Windows looks for python.exe from the “Environment Variables”, specifically checks the PATH variable. If you want to know from where the executable got resolved, you can use a handy utility called where.exe:
Encountered a mysterious issue these days: stopped the App Service on Azure, but the application was still logging, like nothing happened. Waiting couple of minutes, then half an hour, but logs were still coming.
Checked the generated url and the site responded as it should:
Turned out, that the App Service was hosting WebJobs, not a classic web app and the default “Stop” doesn’t apply to them. To turn off WebJobs, one need to navigate to WebJobs blade of the App Service.
Generally an event subscription looks something like this:
// Creating a timer
System.Timers.Timer t = new(1000);
// Subscribing on it's elapsed event
t.Elapsed += T_Elapsed;
// Starting the timer
t.Start();
// Implementing the timers' elapsed event
void T_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Tick!");
}
// Not letting the app to exit
Console.ReadLine();
We have an event emitter, the timer, and we are subscribing and implementing a method when that event is emitted.
It is possible to shorten this event implementation in one line:
// Creating a timer
System.Timers.Timer t = new(1000);
// Subscribing and implementing on it's elasped event
t.Elapsed += (_, _) => { Console.WriteLine("Tick!"); };
// Starting the timer
t.Start();
// Not letting the app to exit
Console.ReadLine();
Note: the (_, _) is equal to (sender, e), we just shorten them because we won’t use them.
Although it can be convenient to use this form regularly, but take care and keep the code readable!
Nowadays for a complex web application it is almost always necessary to write a WebAPI. One way to test these endpoints during and after implementation is to manually create our own http clients, which is time consuming and hard to follow the constant changes, which can occur regularly with a new API. There are many tools for this purpose. Probably one of the most well known is Swagger, which we are going to showcase.
Start a new ASP.NET Empty project. We are adding a new folder named Controllers and a controller named HomeController.cs to it. Our structure should look like this:
New we are extending the HomeController with our two endpoints:
[Route("api/home")]
public class HomeController : Controller
{
[HttpGet]
[Route("getMessage/{message}")]
public ActionResult<string> Get(string message)
{
return $"Your message from get was {message}";
}
[HttpPost]
[Route("postMessage")]
public ActionResult<string> Post([FromBody] string message)
{
return $"Your message from post was {message}";
}
}
Our endpoints should be available on these two urls:
Note: at this state the endpoints are not served as we haven’t configured our site to interact with controllers.
Let’s configure our website to serve our endpoints and use Swagger+SwaggerUI. From Nuget we need to add Swashbuckle.AspNetCore.SwaggerGen and Swashbuckle.AspNetCore.SwaggerUI packages. As all of our dependencies are in place we can go to Program.cs and setup these:
var builder = WebApplication.CreateBuilder(args);
// Telling ASP that we want to use the controller feature
builder.Services.AddControllers();
// Adding swagger code generator (and it's dependencies) to the services
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Mapping the endpoints in the controllers to serve them
app.MapControllers();
// Registering swagger middleware
app.UseSwagger();
// Registering the UI service
app.UseSwaggerUI();
// Starting the website
app.Run();
Running our application will fail to load the default page, because we don’t have any. But if we add swagger at the end of our url, the SwaggerUI should appear:
We can click on the endpoint dropdowns and try them out by adding parameters and clicking on the Execute button.
I don’t really like the default mechanism of Visual Studio, that it starts a new browser instance every time we start our website. It is quite easy to solve this problem. Look for the launchSettings.json under Properties folder. Search for the profile you are starting and set the launchBrowser to false. Thats all!