c# - 无法将 REST API 用于 Windows Server 1.1(本地)的服务总线

标签 c# rest azure servicebus azureservicebus

我正在使用 Window Server 服务总线 1.1。我可以使用以下基地址从 Window Server 服务总线生成 OAuth token

  string baseAddressHttp = "https://" + ServerName + ":9355/" + Namespace + "/$STS/OAuth/"; 

对于用于将消息发送到队列的 Window Azure 服务总线,我可以在以下队列地址上发布请求

        string serviceNamespace = "ServiceBusDefaultNamespace";
        string queueName = "SampleQueuName";
        string message ="This is my first message";
        string queueAddress = "https://" + serviceNamespace + ".servicebus.windows.net/"+ queueName + "/messages";
        WebClient webClient = new WebClient();
        webClient.Headers[HttpRequestHeader.Authorization] = token;
        webClient.UploadData(baseAddress, "POST", Encoding.UTF8.GetBytes(message));

但是对于窗口服务器服务总线,同样的技术不起作用。

Window Server Service Bus 1.1 是否支持 REST API? 任何帮助将不胜感激。

提前致谢!!

最佳答案

是的,它确实支持它。我们正在使用它。

  1. 我认为您的默认命名空间端点错误 - 您不需要 .servicebus.windows.net
  2. 您需要首先使用具有服务总线监听或发送权限的用户的用户名和密码从 sts 获取 token 。
  3. 服务总线用户的用户名和密码必须以特定格式发布。
  4. 然后,您需要将返回的 token 添加到授权 header 中,并向/messages 端点发出实际的发送或监听请求。
  5. 这段代码应该可以做到这一点:

    private const string DefaultNamespace = "https://yoursbserver:9355/servicebusdefaultnamespace";
    private const string QueueEndpoint = "https://yoursbserver:9355/servicebusdefaultnamespace/YourQueueNameOrTopicName/messages/?timeout=60";
    
    private static void Main()
    {
        var token = GetOAuthTokenFromSts(new Uri(DefaultNamespace), "usernamewithpermissiononServiceBus", "password", TimeSpan.FromMinutes(10));
        var messageXml = CreateXml();
        SendMessage(token, messageXml);
    
        Console.WriteLine("Successfully posted message!");
        Console.ReadLine();
    }
    
    private static string CreateMessage()
    {
        return "<SomeMessage xmlns='MyNamespace'></SomeMessage>";
    }
    
    public static string GetOAuthTokenFromSts(Uri namespaceBaseAddress, string userName, string userPassword, TimeSpan timeout)
    {
        const string stsPath = "$STS/OAuth/";
    
        var requestUri = new Uri(namespaceBaseAddress, stsPath);
        var requestContent = GetRequestContent(namespaceBaseAddress, userName, userPassword);
        var request = CreateRequest(timeout, requestUri, requestContent);
        return GetAccessToken(request, requestContent);
    }
    
    private static HttpWebRequest CreateRequest(TimeSpan timeout, Uri requestUri, byte[] requestContent)
    {
        var request = WebRequest.Create(requestUri) as HttpWebRequest;
        request.ServicePoint.MaxIdleTime = 5000;
        request.AllowAutoRedirect = true;
        request.MaximumAutomaticRedirections = 1;
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = requestContent.Length;
        request.Timeout = Convert.ToInt32(timeout.TotalMilliseconds,
                                          CultureInfo.InvariantCulture);
        return request;
    }
    
    private static byte[] GetRequestContent(Uri namespaceBaseAddress, string userName, string userPassword)
    {
        const string clientPasswordFormat = "grant_type=authorization_code&client_id={0}&client_secret={1}&scope={2}";
        var requestContent = string.Format(CultureInfo.InvariantCulture,
                                              clientPasswordFormat, HttpUtility.UrlEncode(userName),
                                              HttpUtility.UrlEncode(userPassword),
                                              HttpUtility.UrlEncode(namespaceBaseAddress.AbsoluteUri));
        return Encoding.UTF8.GetBytes(requestContent);
    }
    
    private static string GetAccessToken(HttpWebRequest request, byte[] requestContent)
    {
        string accessToken;
        using (var requestStream = request.GetRequestStream())
        {
            requestStream.Write(requestContent, 0, requestContent.Length);
        }
    
        using (var response = request.GetResponse() as HttpWebResponse)
        using (var stream = response.GetResponseStream())
        using (var reader = new StreamReader(stream, Encoding.UTF8))
        {
            accessToken = reader.ReadToEnd();
        }
    
        return string.Format(CultureInfo.InvariantCulture, "WRAP access_token=\"{0}\"", accessToken);
    }
    
    private static void SendMessage(string token, string message)
    {
        var webClient = new WebClient();
        webClient.Headers[HttpRequestHeader.Authorization] = token;
        webClient.UploadData(QueueEndpoint, "POST", Encoding.UTF8.GetBytes(message));
    }
    

关于c# - 无法将 REST API 用于 Windows Server 1.1(本地)的服务总线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21678274/

相关文章:

c# - 公共(public)内部类

c# - 文件编码未知时如何使用ReadAllText

c# - C# 中的 SQL 依赖

c# - REST Api 为同一对象返回不同的对象名称,如何使用 RestSharp 处理?

python - Django Rest auth user_logged_in 信号

Mysql 返回一个不正确的 bigint 结果,非常奇怪的错误

azure - 为什么 'Azure Kubernetes Service RBAC Reader' 角色允许部署写入

c# - 使用线程遍历数组以每秒显示一个项目

git - 将 NodeJS 应用程序部署到 Azure 网站时,从部署.cmd 中的 pages.json 安装 NPM 包失败?

c# - 为什么 RoleEnvironment.IsEmulated 通常不用于区分 Azure 云和计算模拟器?