Prerequisites
An environment variable named AzureServiceBus.
with the connection string for the Azure Service Bus namespace.
Azure Service Bus Transport
This sample uses the Azure Service Bus Transport (Legacy).
Code walk-through
This sample has two endpoints
Publisher
Subscriber
Publisher
Publisher
publishes SomeEvent
.
public class SomeEvent :
IEvent
{
public Guid EventId { get; set; }
}
Subscriber
Subscriber
subscribes to and handles SomeEvent
. The topology used by the endpoints is ForwardingTopology
, which creates a subscription named Subscriber
and creates a rule for each event the endpoint subscribes to.
SomeEvent
full name is Shared.
. That is 72 characters which exceed the maximum 50 characters limit for a rule name. An attempt to use such a long rule name will result in the following exception:
Invalid Rule name 'Shared.Messages.In.A.Deep.Nested.Namespace.Nested.Events.SomeEvent' that cannot be used with Azure Service Bus. Rule name exceeds maximum allowed length or contains invalid characters. Check for invalid characters, shorten the name, or use 'Sanitization().UseStrategy
()' configuration extension.`
Creating custom sanitization
Registering custom sanitization
For the purpose of this sample, custom sanitization based on a SHA1 hashing algorithm will be used to generate a valid rule name:
class Sha1Sanitization :
ISanitizationStrategy
{
public string Sanitize(string entityPathOrName, EntityType entityType)
{
// remove invalid characters
if (entityType == EntityType.Queue || entityType == EntityType.Topic)
{
var regexQueueAndTopicValidCharacters = new Regex(@"[^a-zA-Z0-9\-\._\/]");
var regexLeadingAndTrailingForwardSlashes = new Regex(@"^\/|\/$");
entityPathOrName = regexQueueAndTopicValidCharacters.Replace(entityPathOrName, string.Empty);
entityPathOrName = regexLeadingAndTrailingForwardSlashes.Replace(entityPathOrName, string.Empty);
}
if (entityType == EntityType.Subscription || entityType == EntityType.Rule)
{
var rgx = new Regex(@"[^a-zA-Z0-9\-\._]");
entityPathOrName = rgx.Replace(entityPathOrName, "");
}
var entityPathOrNameMaxLength = 0;
switch (entityType)
{
case EntityType.Queue:
case EntityType.Topic:
entityPathOrNameMaxLength = 260;
break;
case EntityType.Subscription:
case EntityType.Rule:
entityPathOrNameMaxLength = 50;
break;
}
// hash if too long
if (entityPathOrName.Length > entityPathOrNameMaxLength)
{
entityPathOrName = SHA1DeterministicNameBuilder.Build(entityPathOrName);
}
return entityPathOrName;
}
}
Generated hash (20 bytes) will be formatted into eight groups of 8 characters each for readability:
static class SHA1DeterministicNameBuilder
{
public static string Build(string input)
{
using (var provider = new SHA1CryptoServiceProvider())
{
var inputBytes = Encoding.Default.GetBytes(input);
var hashBytes = provider.ComputeHash(inputBytes);
var hashBuilder = new StringBuilder(string.Join("", hashBytes.Select(x => x.ToString("x2"))));
foreach (var delimeterIndex in new[]
{
5,
11,
17,
23,
29,
35,
41
})
{
hashBuilder.Insert(delimeterIndex, "-");
}
return hashBuilder.ToString();
}
}
}
Custom strategy registration:
var sanitization = transport.Sanitization();
sanitization.UseStrategy<Sha1Sanitization>();
Generated rule name: