Azure App Service release hangs and then fails

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:

A release hangs for a long time and then fails, a “503 service unavailable” error occurs, or the deployment history in the deployment logs fails to update

It turned out that the App Service Plan was hosting multiple, small services which took most of the resources, making the deployment hazardous.

Increasing the App Service Plan’s tier solved our issue.

Cannot update to higher App Service tiers

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:

Error when upgrading through Azure CLI

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.

Check availability of App Service Plan in your region

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.

az appservice list-locations --sku P5mv3

The code above gets which regions have P5mv3 VMs. To look for SKU-s, you can visit Azure’s App Service Plan pricing page.

Find out executable resolve path

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:

where python

Of course, we can where the where🙂

where where

Happy coding!

Azure App Service still logging when stopped

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.

Azure App Service stop

Checked the generated url and the site responded as it should:

Error 403 - Site is stopped

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.

String templating with dollar sign

There are many different ways to construct a string in C#. One of the most convenient way is to use the dollar sign ($). As shown in this example:

string stringVar = "myStringVar";
int intVar = 2022;
double doubleVar = 2022.22;
object objectVar = new {  objectStringVar = "objectStringVar" , objectIntVar = 22 };

string templatedString = $"This is a stringVar: {stringVar}, " +
    $"that one is an intVar: {intVar}, " +
    $"here comes doubleVar: {doubleVar} , " +
    $"finally the objectVar: {objectVar}";

Console.WriteLine(templatedString);
Console.ReadLine();

This one will produce the following result:

Happy coding!

One liner event subscription in C#

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!

Happy coding!

Visualize and test our ASP.NET API

Goal of this post is to show how easy it is to add visualization and testing option to our API using Swagger.

Tool/prerequisites we are going to use: Visual Studio, .NET 6, ASP.NET, Swashbuckle.AspNetCore.SwaggerGen and Swashbuckle.AspNetCore.SwaggerUI as NuGet dependencies.

GitRepo is available here.

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:

Project structure

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:

localhost:port/api/home/getMessage/{message}
localhost:port/api/home/postMessage

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:

SwaggerUI page

We can click on the endpoint dropdowns and try them out by adding parameters and clicking on the Execute button.

Happy coding!

Don’t open new browser when starting ASP.NET website

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!

Happy coding!