Sending a message to a azure service bus queue in

2019-02-28 07:01发布

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 send a message to the queue using the REST API?

3条回答
Luminary・发光体
2楼-- · 2019-02-28 07:25

While the current client is not .NET Core compatible, the new client, that is a work in progress, is 100% compatible. The pre-release package will be available on April 3rd and the status can be tracked here. You could pull down the course code and compile it already today with the caveat that API will be changing as the team is trying to flesh out the design details.

查看更多
Viruses.
3楼-- · 2019-02-28 07:25

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
{
    /// <summary>
    /// Publish domain events to domain topic.
    /// </summary>
    Task PublishAsync<T>(T @event)

    /// <summary>
    /// Send commands to command queue.
    /// </summary>
    Task SendAsync<T>(T command)
}

public class ServiceBus : IServiceBus
{
    private readonly AzureServiceBusSettings _settings;

    public ServiceBus(IOptions<AzureServiceBusSettings> azureServiceBusSettings)
    {
        _settings = azureServiceBusSettings.Value;
    }

    /// <summary>
    /// Publish domain events to domain topic.
    /// </summary>
    public async Task PublishAsync<T>(T @event)
    {
        await SendInternalAsync(@event, "domain");
    }

    /// <summary>
    /// Send commands to command queue.
    /// </summary>
    public async Task SendAsync<T>(T command)
    {
        await SendInternalAsync(command, "commands");
    }

    private async Task SendInternalAsync<T>(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<IOptions<AzureServiceBusSettings>> _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<IOptions<AzureServiceBusSettings>>();
        _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.
    }
}
查看更多
在下西门庆
4楼-- · 2019-02-28 07:33

Can anyone show me how to send a message to the queue using the REST API?

As 4c74356b41 mentioned in his comment, we could send a message to Azure Service Bus queue via this REST API:

POST http{s}://{serviceNamespace}.servicebus.windows.net/{queuePath|topicPath}/messages

here is a example

enter image description here

In above request, I provide a Shared Access Signature (token), to generate a Shared Access Signature (token), please refer to this article.

查看更多
登录 后发表回答