【发布时间】:2017-08-19 05:49:33
【问题描述】:
我想在 .Net Core 中向我的 Azure 服务总线队列发送消息,但 WindowsAzure.ServiceBus 包与 .Net Core 不兼容。
谁能告诉我如何使用 REST API 向队列发送消息?
【问题讨论】:
标签: rest azure asp.net-core servicebus azure-servicebus-queues
我想在 .Net Core 中向我的 Azure 服务总线队列发送消息,但 WindowsAzure.ServiceBus 包与 .Net Core 不兼容。
谁能告诉我如何使用 REST API 向队列发送消息?
【问题讨论】:
标签: rest azure asp.net-core servicebus azure-servicebus-queues
感谢 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.
}
}
【讨论】:
虽然 current client 与 .NET Core 不兼容,但正在开发中的 new client 100% 兼容。预发布包将于 4 月 3 日发布,状态可追踪here。您现在可以下载课程代码并编译它,但需要注意的是,随着团队试图充实设计细节,API 将会发生变化。
【讨论】:
谁能告诉我如何使用 REST API 向队列发送消息?
正如 4c74356b41 在他的评论中提到的,我们可以通过 this REST API 向 Azure 服务总线队列发送消息:
POST http{s}://{serviceNamespace}.servicebus.windows.net/{queuePath|topicPath}/messages
这是一个例子
在上述请求中,我提供了一个共享访问签名(token),生成共享访问签名(token),请参考this article。
【讨论】: