【问题标题】:Sending a message to a azure service bus queue in .Net Core Core using the REST API使用 REST API 向 .Net Core Core 中的 Azure 服务总线队列发送消息
【发布时间】:2017-08-19 05:49:33
【问题描述】:

我想在 .Net Core 中向我的 Azure 服务总线队列发送消息,但 WindowsAzure.ServiceBus 包与 .Net Core 不兼容。

谁能告诉我如何使用 REST API 向队列发送消息?

【问题讨论】:

标签: rest azure asp.net-core servicebus azure-servicebus-queues


【解决方案1】:

感谢 Fred 的回答,我已经扩展到包括如何发布带有签名的身份验证标头。

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;
        }
    }
}

还有一个简单的 xunit 测试要发布:

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.
    }
}

【讨论】:

    【解决方案2】:

    虽然 current client 与 .NET Core 不兼容,但正在开发中的 new client 100% 兼容。预发布包将于 4 月 3 日发布,状态可追踪here。您现在可以下载课程代码并编译它,但需要注意的是,随着团队试图充实设计细节,API 将会发生变化。

    【讨论】:

    • 非常感谢!我现在可以通过安装 nuget 包来发送消息。
    • 昨天在 nuget 上发布了一个 alpha 版本。所以现在它是真实的:)
    • 如果我们想针对 .NET Core 2.0 或 .NETStandard 2 怎么办?
    • 它是 .NET Standard 1.3 compliant,因此定位 .NET Standard 2.0 或 .NET Core 2.0 应该不成问题。顺便说一句,新客户端最近已 GA-ed,因此您可以将其用于生产代码。
    • 这很奇怪,微软在他们的消息传递平台和产品上投入了如此多的投资,而对其主要开发平台 API 的支持却如此之少。多年来针对“旧”客户端库进行编程的人现在陷入困境。 “新”库大不相同,甚至没有某种迁移指南的迹象。去弄清楚。
    【解决方案3】:

    谁能告诉我如何使用 REST API 向队列发送消息?

    正如 4c74356b41 在他的评论中提到的,我们可以通过 this REST API 向 Azure 服务总线队列发送消息:

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

    这是一个例子

    在上述请求中,我提供了一个共享访问签名(token),生成共享访问签名(token),请参考this article

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 2012-08-28
      • 2016-02-25
      • 1970-01-01
      • 2013-03-19
      • 2022-12-19
      • 1970-01-01
      相关资源
      最近更新 更多