Sending a message to a azure service bus queue in .Net Core Core using the REST API

后端 未结 3 2025
清歌不尽
清歌不尽 2021-01-22 00:41

I want to send a message to my Azure Service Bus Queue in .Net Core but the WindowsAzure.ServiceBus Package is not compatible with .Net Core.

Can anyone show me how to s

3条回答
  •  旧巷少年郎
    2021-01-22 01:13

    Thanks to Fred's answer, I've expanded to include how to post the authentication header with signature.

    public class AzureServiceBusSettings
    {
        public string BaseUrl { get; set; }
        public string SharedAccessKey { get; set; }
        public string SharedAccessKeyName { get; set; }
    }
    
    public interface IServiceBus
    {
        /// 
        /// Publish domain events to domain topic.
        /// 
        Task PublishAsync(T @event)
    
        /// 
        /// Send commands to command queue.
        /// 
        Task SendAsync(T command)
    }
    
    public class ServiceBus : IServiceBus
    {
        private readonly AzureServiceBusSettings _settings;
    
        public ServiceBus(IOptions azureServiceBusSettings)
        {
            _settings = azureServiceBusSettings.Value;
        }
    
        /// 
        /// Publish domain events to domain topic.
        /// 
        public async Task PublishAsync(T @event)
        {
            await SendInternalAsync(@event, "domain");
        }
    
        /// 
        /// Send commands to command queue.
        /// 
        public async Task SendAsync(T command)
        {
            await SendInternalAsync(command, "commands");
        }
    
        private async Task SendInternalAsync(T command, string queueName)
        {
            var json = JsonConvert.SerializeObject(command);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
    
            using (var httpClient = new HttpClient())
            {
                httpClient.BaseAddress = new Uri(_settings.BaseUrl);
    
                try
                {
                    var url = $"/{queueName}/messages";
    
                    httpClient.DefaultRequestHeaders.Authorization =
                        new AuthenticationHeaderValue("SharedAccessSignature", GetSasToken(queueName));
    
                    var response = await httpClient.PostAsync(url, content);
    
                    // Success returns 201 Created.
                    if (!response.IsSuccessStatusCode)
                    {
                        // Handle this.
                    }
                }
                catch (Exception ex)
                {
                    // Handle this.
                    // throw;
                }
            }
        }
    
        private string GetSasToken(string queueName)
        {
            var url = $"{_settings.BaseUrl}/{queueName}";
            // Expiry minutes should be a setting.
            var expiry = (int)DateTime.UtcNow.AddMinutes(20).Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
            var signature = GetSignature(url, _settings.SharedAccessKey);
            var token = $"sr={WebUtility.UrlEncode(url)}&sig={WebUtility.UrlEncode(signature)}&se={expiry}&skn={_settings.SharedAccessKeyName}";
            return token;
        }
    
        private static string GetSignature(string url, string key)
        {
            var expiry = (int)DateTime.UtcNow.AddMinutes(20).Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
            var value = WebUtility.UrlEncode(url) + "\n" + expiry;
            var encoding = new UTF8Encoding();
            var keyByte = encoding.GetBytes(key);
            var valueBytes = encoding.GetBytes(value);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                var hashmessage = hmacsha256.ComputeHash(valueBytes);
                var result = Convert.ToBase64String(hashmessage);
                return result;
            }
        }
    }
    

    And a simple xunit test to post:

    public class ServiceBusTests
    {
        public class FooCommand : ICommand
        {
            public Guid CommandId { get; set; }
        }
    
        private Mock> _mockAzureServiceBusOptions;
    
        private ServiceBus _sut;
    
        public ServiceBusTests()
        {
            var settings = new AzureServiceBusSettings
            {
                BaseUrl = "https://my-domain.servicebus.windows.net",
                SharedAccessKey = "my-key-goes-here",
                SharedAccessKeyName = "RootManageSharedAccessKey"
            };
    
            _mockAzureServiceBusOptions = new Mock>();
            _mockAzureServiceBusOptions.SetupGet(o => o.Value).Returns(settings);
    
            _sut = new ServiceBus(
                _mockAzureServiceBusOptions.Object);
        }
    
        [Fact]
        public async Task should_send_message()
        {
            // Arrange.
            var command = new FooCommand {CommandId = Guid.NewGuid()};
    
            // Act.
            await _sut.SendAsync(command);
    
            // Assert.
            // TODO: Get the command from the queue and assert something.
        }
    }
    

提交回复
热议问题