Wednesday, February 26, 2025

.NET 10 Preview 1.0: Numeric Ordering for String Comparison

After so much of waiting, the first preview of .NET 10 is now available. This comes with new .NET libraries, some new C# 14 features and many more.

In this post let's have a look a new .NET library feature that was initially requested back in 2015, and finally that's made into .NET 10.

Consider the following list of strings.
List<string> strings =
[
    "3",
    "5",
    "05",
    "10",
    "11"
];
If you order these by doing something below,
IOrderedEnumerable<string> orderedStrings = strings.Order();
The order would be,
05
10
11
3
5
These are lexicographically ordered. But numerically, "3" is less than "05" and also "5" and "05" are equal.

Now we have new NumericOrdering comparer for strings.
// The new numerical string comparer
StringComparer numericStringComparer =  StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);
IOrderedEnumerable<string> orderedStrings = strings.Order(numericStringComparer);
And now the output would be as we expect.
3
5
05
10
11
Love it.

Read more:

Happy Coding.

Regards,
Jaliya

Monday, February 17, 2025

Azure DevOps Classic Release Pipelines: Read Variables in a Variable Group and Update Azure App Service AppSettings

In this post let's see how to read variables in a Variable Group and deploy them to Azure App Service as app settings from a Classic Azure DevOps Release Pipeline.

In the release pipeline I have Azure CLI task added and the release pipeline is running on Azure Hosted windows-latest agent.

Release Pipeline
In the Azure CLI task, I am doing the following.

Acquire a PAT (Personal Access Token) and set it.

$PAT = "<YOUR_PAT>"
$env:AZURE_DEVOPS_EXT_PAT = $PAT

Now set the default organization and project for az devops command.

az devops configure --defaults `
    organization=https://dev.azure.com/<YOUR_ORGANIZATION>/ `
    project=<YOUR_PROJECT>

Get list of variables in the variable group by Variable Group Id. You can find Variable Group Id in the URL of the Variable Group detail page.

$variablesJson = az pipelines variable-group variable list `
    --group-id <YOUR_VARIABLE_GROUP_ID> `
    --org https://dev.azure.com/<YOUR_ORGANIZATION>/ `
    --project <YOUR_PROJECT>

If we output $variablesJson, it would be something like following.

{
  "SomeOptions__Key1": {
    "isSecret"null,
    "value""<Value1>"
  },
  "SomeOptions__Key2": {
    "isSecret"null,
    "value""<Value2>"
  }
}

Convert the $variablesJson to app settings format that Azure App Service expects.

$variablesAppSettings = $variablesJson `
    | ConvertFrom-Json `
    | ForEach-Object { $_.PSObject.Properties } `
    | ForEach-Object ` {
        $key = $_.Name
        $value = $_.Value.value
        @{ 
            name = $key;
            slotSetting = $false;
            value = $value 
        }
}

Save the app settings to a temporary file.

ConvertTo-Json $variablesAppSettings | Out-File "$(System.DefaultWorkingDirectory)\appsettings-updated.json"

appsettings-updated.json would look like below.

[
  {
    "name""SomeOptions__Key1",
    "value""<Value1>",
    "slotSetting"false
  },
  {
    "name""SomeOptions__Key2",
    "value""<Value2>",
    "slotSetting"false
  }
]

Now finally update the app settings in the web app.

$resourceGroup = "<resourceGroup>"
$webAppName = "<webAppName>"

az webapp config appsettings set `
    --resource-group $resourceGroup `
    --name $webAppName `
    --settings "@$(System.DefaultWorkingDirectory)\appsettings-updated.json"

Hope this helps.

Happy Coding.

Regards,
Jaliya

Monday, February 10, 2025

Visual Studio 2022: HTTP Files and Request Variables

It's a very common scenario that we want to call an endpoint and use the result in subsequent requests. In this post, let's see how we can make use of Request Variables in .http files in Visual Studio 2022 to achieve that. Request Variable is a special kind of a variable (see my previous post for use of variables Visual Studio 2022: HTTP Files and Variables).

So let's start. The first step is to give a request a name.
@HostAddress = http://localhost:5200

### CREATE
# @name createEmployee

POST {{HostAddress}}/employees
Content-Type: application/json
{
   "firstName": "John",
   "lastName": "Doe"
}
Here, the comment: # @name createEmployee which is located just before the request specifies the name of the request. You can use following syntax if you prefer, which is also valid.
// @name createEmployee
Now we can reference this particular named request (createEmployee) using following syntax.
{{<requestName>.(response|request).(body|headers).(*|JSONPath|XPath|<headerName>)}}
For example, say the above endpoint is returning a JSON response, something like the following.
POST: Employee
Now I can use the returned id to Get the employee by Id.
### GET by Id
GET {{HostAddress}}/employees/{{createEmployee.response.body.$.id}}
Accept: application/json
GET: Employee
I can even use the request variable in the request body. Say I want to update the existing employee with a different lastName.
### UPDATE
PUT {{HostAddress}}/employees/{{createEmployee.response.body.$.id}}
Content-Type: application/json
{
    "id": "{{createEmployee.response.body.$.id}}",
    "firstName": "{{createEmployee.response.body.$.firstName}}",
    "lastName": "Bloggs"
}
PUT: Employee

Hope this helps.

Happy Coding.

Regards,
Jaliya

Wednesday, February 5, 2025

Azure DevOps Classic Release Pipelines: Using Task Group Parameters to Control Task Execution

In this post let's see how we can use Parameters in a Task Group to control Task execution in Azure DevOps Classic Release Pipelines.

Let's say we have a Task Group that accepts following parameter.
Task Group Parameter
Now based on the value (true/false) passed in for this parameter, say I want to skip a particular Task. For that, we can use tasks Control Options -> Run this task -> Custom conditions.
Control Options -> Run this task -> Custom conditions
First step is initializing a release level variable with the value of the parameter. Note: I couldn't figure out how to access parameters directly in the condition, hence using a variable. If you find out a way, please do leave a comment. 

We can add in a PoweShell Task and do follows to initialize a variable.
Write-Host "##vso[task.setvariable variable=varIsSkipTask]$(IsSkipTask)"
Set Variable
And now, we can use the variable in custom condition as follows.
and(succeeded(), ne(variables['varIsSkipTask'], 'true'))
Control Options -> Run this task -> Custom conditions: Skip Task
And that's it.

Now when I run a release with IsSkipTask = true ,
IsSkipTask = true
Task is Skipped.
Task is skipped
Else,
Task is not skipped
Task is not getting skipped.

Hope this helps.

Happy Coding.

Regards,
Jaliya