Introduction
The other day, we were sending some messages to services wherein a messageID
was required. We used to create a messageID
by using a Guid.NewGuid()
, but the one of the receiving services threw an exception. It turned out that this one particular service defined the messageID
to be only 30 characters or less. So what to do?
Some of us thought it would be a wise idea to use some form of timestamp in combination with a system identifier. Well, as you can imagine, in an environment that would produce a lot of messages, the chance of that messageID
being unique drops dramatically. We wanted to stick with the Guid.
Okay, sticking with the Guid, maybe we can just remove the '-' and truncate the resulting string
to 30 characters. Sure, that might work. Still, we are reducing the uniqueness. There must be a better way.
The Solution
We found that converting the Guid (16 bytes) to an ASCII representation using Base64
resulted in a useable and still unique messageID
of only 22 characters.
var newGuid = Guid.NewGuid();
var messageID = Convert.ToBase64String(newGuid.ToByteArray());
For example: The Guid 'e6248889-2a12-405a-b06d-9695b82c0a9c
' (string length: 36) will get a Base64
representation: 'iYgk5hIqWkCwbZaVuCwKnA==
' (string length: 24)
The Base64
representation ends with the '==
' characters. You could just truncate these, without any impact on the uniqueness. Leaving you with an identifier of only 22 characters in length.
Proof
Just saying that this works might suffice, but here is a small piece of code that you can run that will prove that the Guid you convert can be converted back to the Guid you started with; ergo, the resulting string is as unique as the starting Guid.
using System;
var newGuid = Guid.NewGuid();
Console.WriteLine($"GUID: {newGuid.ToString()}");
Console.WriteLine($"length: {newGuid.ToString().Length}" );
var base64 = Convert.ToBase64String(newGuid.ToByteArray());
Console.WriteLine($"Base64 representation: {base64}");
Console.WriteLine($"length: {base64.Length}" );
var reconstructedGuid = new Guid(Convert.FromBase64String(base64));
Console.WriteLine($"Restored GUID: {reconstructedGuid.ToString()}");
Console.WriteLine("Restore from Base64 : " + (reconstructedGuid==newGuid?"PASSED": "FAILED"));
Points of Interest
Please have a look at the blogpost Equipping our ASCII Armor by Jeff Atwood for more information on using a Guid in different forms. His blogpost inspired this tip.