BugOfTheDay: There are pending requests working on this transaction

These days I got this exception message: “The transaction operation cannot be performed because there are pending requests working on this transaction.” This is how I fixed it after almost a whole day of Googling and debugging.

To fix the “pending requests” exception, make sure to properly await all asynchronous methods wrapped inside any database transaction.

Pipeline pattern and reverting reservations

I was working with the pipeline pattern to book online reservations.

The reservation process used two types of steps inside a pipeline: foreground and background steps.

The foreground steps ran to separate enough rooms for the reservation. And the background steps did everything else to fulfill the reservation but in background jobs.

If anything wrong happened while executing the foreground steps, the whole operation rollbacked. And there were no rooms set aside for the incoming reservation. To achieve this, every foreground step had a method to revert its own operation.

The code to revert the whole pipeline was wrapped inside a transaction. It looked something like this,

using (var transactionScope = _transactionManager.Create(IsolationLevel.Serializable))
{
    try
    {
        await pipeline.RevertAsync();

        transactionScope.Commit();
    }
    catch (Exception e)
    {
        transactionScope.Rollback();

        _logger.LogError(e, "Something horribly horribly wrong happened");

        throw;
    }
}

The Commit() method broke with the exception mentioned earlier. Arrrggg!

Broken display glass
No displays or electronic devices were damaged while debugging this issue. Photo by Julia Joppien on Unsplash

Always await async methods

After Googling for a while, I found a couple of StackOverflow answers that mention to await all asynchronous methods. But, I thought it was a silly mistake and I started to look for something else more complicated.

After checking for a while, trying to isolate the problem, following one of my debugging tips, something like this code got all my attention.

public async Task RevertAsync(ReservationContext context)
{
    var reservation = context.Reservation;
    if (reservation == null)
    {
        return;
    }

    var updatedByUserId = GetSystemUserAsync(context).Id;
    await _roomService.UnassignRooms(reservation, updatedByUserId);
}

private async Task<User> GetSystemUserAsync()
{
    var systemUser = await _userRepository.GetSystemUserAsync();
    return systemUser;
}

Did you notice any asynchronous methods not being awaited? No? I didn’t for a while. Neither did my reviewers.

But, there it was. Unnoticed for the code analyzer too. And, for all the passing tests.

Oh, dear! var updatedByUserId = GetSystemUserAsync(context).Id. This line was the root of the issue. It was meant to log the user Id who performed an operation, not the Id of the Task not being awaited.

Voilà! In case you have to face this exception, take a deep breath and carefully look for any async methods not being awaited inside your transactions.

If you want to read more content, check my debugging tips. To learn to write unit tests, start reading Unit Testing 101. A better failing test would’ve caught this issue.

To read about C# async/await keywords, check my C# Definitive Guide. It contains good resources to be a fluent developer in C#.

Happy bug fixing!

Monday Links: Workplaces, studying and communication

Another Monday Links. Five articles I found interesting in last month.

Don’t waste time on heroic death marches

“Successful companies, whether they’re programming houses, retailers, law firms, whatever, make their employees’ needs a priority.” Totally agree. No more comments! Read full article

How to study effectively

One of my favorite subjects: how to study. Don’t cram. Don’t reread the material. Don’t highlight. Instead, study in short sessions and recall the material. Easy! There are even more strategies. Read full article

Undervalued Software Engineering Skills: Writing Well

We, as developers, spend a lot of time writing prose, not only code. Commit messages, ticket and PR descriptions, README files. We should get better at it. To check my writings, I use the Hemingway app often. Read full article

women sitting on chairs
Once upon a time, there were no Zoom calls. Photo by Boston Public Library on Unsplash

15 signs you joined the wrong company as a developer

Number 12. and 13. are BIG red flags. Let’s pay attention to those. Recently, I read about “disagree with your feet.” It resonates with this article. When you don’t like something about your job and you can’t do anything about it, walk away. Read full article

No, we won’t have a video call for that

I don’t like those chat messages with only “Hi!” or “How are you?” when we both know that’s not the message. This article shows how to better communicate on remote teams. Embrace asynchronous communication. Prefer (in order) Issue tracker, Wiki, email, and chat. Stay away from video calls as much as possible. Don’t ping people on chat software. And other ideas. Read full article, Watch full presentation.

Voilà! This Monday Links ended up being about better workplaces. See you in a month or two in the next Monday Links! In the meantime, grab your own copy of my free eBook Unit Testing 101. Don’t miss the previous Monday Links on Farmers, Incidents and Holmes.

Happy reading!

TIL: Dictionary keys are converted to lowercase too on serialization

Today, I needed to pass a dictionary between two ASP.NET Core 6.0 API sites. To my surprise, on the receiving side, I got the dictionary with all its keys converted to lowercase instead of PascalCase. I couldn’t find any element on the dictionary, even though the keys had the same names on each API site. This is what I learned about serializing dictionary keys.

Serialization with Newtonsoft.Json

It turns out that the two API sites were using Newtonsoft.Json for serialization. Both of them used the CamelCasePropertyNamesContractResolver when adding Newtonsoft.Json.

Something like this,

using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    // ^^^^^
    {
        options.SerializerSettings.NullValueHandling
            = NullValueHandling.Ignore;

        options.SerializerSettings.ContractResolver
            = new CamelCasePropertyNamesContractResolver();
            //    ^^^^^
            // This is what I mean
    });

var app = builder.Build();
app.MapControllers();
app.Run();

With CamelCasePropertyNamesContractResolver, Newtonsoft.Json writes property names in camelCase. But, Newtonsoft.Json treats dictionary keys like properties too.

That was the reason why I got my dictionary keys in lowercase. I used one-word names and Newtonsoft.Json made them camelCase.

To prove this, let’s create a simple controller that read and writes a dictionary. Let’s do this,

using Microsoft.AspNetCore.Mvc;

namespace LowerCaseDictionaryKeys.Controllers;

[ApiController]
[Route("[controller]")]
public class DictionaryController : ControllerBase
{
    [HttpPost]
    public MyViewModel Post(MyViewModel input)
    {
        return input;
        //     ^^^^^
        // Just return the same input
    }
}

public class MyViewModel
{
    public IDictionary<string, string> Dict { get; set; }
}

Now, let’s notice in the output from Postman how the request and the response differ. The keys have a different case. Arggg!

Postman request and response bodies
Postman request and response bodies

1. Configure Newtonsoft.Json naming strategy

To preserve the case of dictionary keys with Newtonsoft.Json, configure the ContractResolver setting with CamelCaseNamingStrategy class and set its ProcessDictionaryKeys property to false.

When registering Newtonsoft.Json, in the SerializerSettings option, let’s do:

using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    // ^^^^^
    {
        options.SerializerSettings.NullValueHandling
            = NullValueHandling.Ignore;

        options.SerializerSettings.ContractResolver
            = new CamelCasePropertyNamesContractResolver
            {
                NamingStrategy = new CamelCaseNamingStrategy
                {
                    ProcessDictionaryKeys = false
                    // ^^^^^
                    // Do not change dictionary keys casing
                }
            };
    });

var app = builder.Build();
app.MapControllers();
app.Run();

For more details, see Newtonsoft.Json docs to Configure NamingStrategy dictionary serialization.

After changing the naming strategy, let’s see the response of our sample controller. That’s what I wanted!

Postman request and response after changing NamingStrategy
Postman request and response bodies

What about System.Text.Json?

To maintain case of dictionary keys with System.Text.Json, let’s set the DictionaryKeyPolicy property inside the JsonSerializerOptions to JsonNamingPolicy.CamelCase.

In our Program.cs class, let’s write,

using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddJsonOptions(options =>
    // ^^^^^
    {
        options.JsonSerializerOptions
            .DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
            // ^^^^^
    });

var app = builder.Build();
app.MapControllers();
app.Run();

For more naming policies, see Microsft docs to customize property names and values with System.Text.Json.

2. Use a comparer with dictionaries

Another alternative is to use a dictionary with a comparer that ignores case of keys.

On the receiving API site, let’s add an empty constructor on the request view model to initialize the dictionary with a comparer to ignore cases.

In my case, I was passing a metadata dictionary between the two sites. I could use a StringComparer.OrdinalIgnoreCase to create a dictionary ignoring the case of keys.

This way, no matter the case of keys, I could find them when using the TryGetValue() method.

public class MyViewModel
{
    public MyViewModel()
    {
        Dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        //                                    ^^^^^
    }

    public Dictionary<string, string> Dict { get; set; }
}

Voilà! That’s how we can configure the case of dictionary keys when serializing requests and how to read dictionaries with keys no matter the case of its keys.

If you want to read about ASP.NET Core, check how to add a caching layer and how to read your appsettings.json configuration file. To avoid KeyNotFoundException and other exceptions when working with dictionaries, check my idioms on dictionaries.

Happy C# time

Don't duplicate logic in Asserts: The most common mistake on unit testing

We have covered some common mistakes when writing unit tests. Some of them may seem obvious. But, we all have made this mistake when we started to write unit tests. This is the most common mistake when writing unit tests and how to fix it.

Don’t repeat the logic under test when verifying the expected result of tests. Instead, use known, hard-coded, pre-calculated values.

Let’s write some tests for Stringie, a (fictional) library to manipulate strings with a fluent interface. Stringie has a Remove() method to remove substrings from the end of a string.

We can use Stringie Remove() method like this,

var hello = "Hello, world!";

string removed = hello.Remove("world!").From(The.End);
// "Hello,"

Don’t Copy and Paste the tested logic

When writing unit tests, don’t copy the tested logic and paste it into private methods to use them inside assertions.

If we bring the tested logic to private methods in our tests, we will have code and bugs in two places. Duplication is the root of all evil. Even, inside our tests.

Please, don’t write assertions like the one in this test.

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(RemoveFromEnd(str, "world!"), transformed);
    //              ^^^^^
    // We duplicate the Remove logic in another method
}

private string RemoveFromEnd(string str, string substring)
{
    var index = str.IndexOf(substring);
    return index >= 0 ? str.Remove(index, substring.Length) : str;
}
building of apartments
That's a lot of duplication. Photo by Joshua Chai on Unsplash

Don’t make internals public

Also, by mistake, we expose the internals of the tested logic to use them in assertions. We make private methods public and static. Even to test those private methods directly.

From our Unit Testing 101, we learned to write unit tests through public methods. We should test the observable behavior of our tested code. A returned value, a thrown exception, or an external invocation.

Again, don’t write assertions like the one in this test.

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(Stringie.PrivateMethodMadePublicAndStatic(str), transformed);
    //              ^^^^^
    // An "internal" method exposed to our tests 
}

Use known values to Assert

Instead of duplicating the tested logic, by exposing internals or copy-pasting code into assertions, use a known expected value.

For our sample test, let’s simply use the expected substring "Hello,". Like this,

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual("Hello,", transformed);
    //              ^^^^^^^^
    // Let's use a known value in our assertions
}

If we end up using the same expected values, we can create constants for them. Like,

const string Hello = "Hello";
// or
const string HelloAndComma = "Hello,";

Voilà! That’s the most common mistake when writing unit tests. It seems silly! But often, we duplicate Math operations and string concatenations and it passes unnoticed. Remember, don’t put too much logic in your tests. Tests should be only assignments and method calls.

If you’re new to unit testing, read my post on how to write your first unit tests in C# with MSTest and check the 4 common mistakes when writing your first tests. Also, don’t miss my Unit Testing 101 series where I cover more subjects like the ones from this post.

Want to write readable and maintainable unit tests in C#? Join my course Mastering C# Unit Testing with Real-world Examples on Udemy and learn unit testing best practices while refactoring real unit tests from my past projects. No more tests for a Calculator class.

Happy testing!

Two C# idioms: On defaults and switch

This post is part of the series "C# idioms"

  1. Two C# idioms
  2. Another two C# idioms
  3. Two C# idioms: On Dictionaries
  4. Two C# idioms: On defaults and switch This post

In this part of the C# idioms series, we have one idiom to write more intention-revealing defaults and another idiom to convert mapping code using a switch to a more compact alternative using a dictionary.

Use intention-revealing defaults

When initializing variables to default values, use intention-revealing alternatives.

Are you initializing a string variable to later assign it? Use "". Do you want to return an empty string from a method? Use string.Empty.

The same is true for collections. If you’re initializing a collection to later add some elements, use the normal constructors like new string[length]; or new List<string>();.

But, if you want to return an empty collection. Use Array.Empty<string>() or Enumerable.Empty<string>().

Replace switch with a dictionary

Replace switch mapping two types with a dictionary.

Turn every value in the case statements into a key in the dictionary. And, turn the returned value in every case into the value of the matching key in the dictionary.

To replace the default case, take advantage of the TryGetValue() or GetValueOrDefault() methods.

Before, to map from a credit card brand name in strings to a CardType enum, we did this,

public static CardType MapToCardType(string cardBrand)
{
    CardType cardType;

    switch (cardBrand)
    {
        case "Visa":
            cardType = CardType.Visa;
            break;

        case "Mastercard":
            cardType = CardType.MasterCard;
            break;

        case "American Express":
            cardType = CardType.AmericanExpress;
            break;

        default:
            cardType = CardType.Unknown;
            break;
    }
    return cardType;
}

After, replacing the switch with a Dictionary,

public static CardType MapToCardType(string cardBrand)
{
    var cardTypeMappings = new Dictionary<string, CardType>
    {
        { "Visa", CardType.Visa },
        { "Mastercard", CardType.Mastercard },
        { "American Express", CardType.AmericanExpress }
    };
    return cardTypeMappings.TryGetValue(cardBrand, out var cardType)
                ? cardType
                : CardType.Unknown;
}

C# 8.0 and Dictionaries

Also, we can use the newer switch syntaxt from C# version 8.0 to write more compact switch.

Starting from C# version 8.0, switch are expressions. It means we can assign switch to variables and use switch as returned values.

Notice how we use a discard _ in the default case to throw an exception.

public static CardType MapToCardType(string cardBrand)
{
    return cardBrand switch
    {
      "Visa" => CardType.Visa,
      "MasterCard" => CardType.MasterCard,
      "American Express" => CardType.AmericanExpress,
      _ => CardType.Unknown
    };
}

Voilà! These are the C# idioms for today. Remember to use intention-revealing defaults and take advantage of the new C# features for switch.

If you want to check more C# recent features, check my Top 16 newest C# features. To get rid of exceptions when working with dictionaries, check Idioms on Dictionaries.

And, don’t miss the other C# Idioms.

Happy coding!