通过 HTTP 添加 Azure 服务总线规则

我正在更改我的代码从 Azure 服务总线订阅接收消息的方式。


以前我使用的是 SDK 类,现在我正在更改为 http REST 调用。


为了为订阅创建规则并为此规则设置过滤器,我总是收到 http 400 作为返回。


看来我创建身体的方式不正确:


            var rule = $"https://{serviceBusNamespace}.servicebus.windows.net/{topicPath}/subscriptions/{subscriptionName}/rules/{ruleName}";


            var content = new StringContent(@"<RuleDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"">

             < Filter i: type = ""SqlFilter"" >

              < SqlExpression > type = 'REPLY' AND username = 'blabla@contoso.com' </ SqlExpression >

             </ Filter >

            </ RuleDescription >

            ", Encoding.UTF8, "application/xml");


            var requestResponse = await _httpClient.PutAsync(rule, content, new System.Threading.CancellationToken());

我还设置了以下标题:


_httpClient.DefaultRequestHeaders.Add("Authorization", _token);

                _httpClient.DefaultRequestHeaders.Add("ContentType", "application/atom+xml");

                _httpClient.DefaultRequestHeaders.Add("Accept", "application/atom+xml");

关于缺少什么的任何想法?


翻阅古今
浏览 142回答 1
1回答

慕田峪7331174

根据错误信息表示请求参数错误。我对提到的api不熟悉,如果可能的话,你可以分享链接。但我建议您可以使用规则 - 创建或更新。我们很容易使用。有关服务总线 api 的更多信息,请参阅此文档。PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ServiceBus/namespaces/{namespaceName}/topics/{topicName}/subscriptions/{subscriptionName}/rules/{ruleName}?api-version=2017-04-01我也为它做了一个演示。1)获取访问令牌private static async Task<string> GetToken(string tenantId, string clientId, string secretKey)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var context = new AuthenticationContext("https://login.windows.net/" + tenantId);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ClientCredential clientCredential = new ClientCredential(clientId, secretKey);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var tokenResponse = await context.AcquireTokenAsync("https://management.azure.com/", clientCredential);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var accessToken = tokenResponse.AccessToken;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return accessToken;&nbsp; &nbsp; &nbsp; &nbsp; }2)关于如何获取tenantId、clientId和秘钥请参考本教程。并且不要忘记分配应用程序的角色。var tenantId = "tenantId";var clientId = "clientId";var secretkey = "sercret Key";var subscriptionId = "subscription Id";var resurceGroup = "resourceGroup";var nameSpace = "servicebus namespace";var topicName = "topicName";var subscription = "service subscription name";var ruleName = "rule name";var token = GetToken(tenantId,clientId,secretkey).Result;using (var httpClient = new HttpClient()){&nbsp; &nbsp;httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);&nbsp; &nbsp;httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));&nbsp; &nbsp;var body = "{\"properties\": { \"filterType\": \"SqlFilter\"},\"sqlExpression\": { \"sqlExpression\": \"myproperty=test\"}}";&nbsp; &nbsp;HttpContent content = new StringContent(body);&nbsp; &nbsp;var url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resurceGroup}/providers/Microsoft.ServiceBus/namespaces/{nameSpace}/topics/{topicName}/subscriptions/{subscription}/rules/{ruleName}?api-version=2017-04-01";&nbsp; &nbsp;var response = httpClient.PutAsync(url, content).Result;&nbsp;}测试结果更新:看来我创建身体的方式不正确:是的,你是对的。根据您提到的API 文档,我们可以知道正文是 xml 格式。但是您的 xml 代码字符串不是 xml 格式,您可以在线使用 xml 验证器。<字符/>和标签之间不应有空格。例如 < Filter i: type = ""SqlFilter"">应该是<Filter i: type = ""SqlFilter"">但它是一个经典的rest api。我们不再定期更新此内容。有关如何支持此产品、服务、技术或 API 的信息,请查看 Microsoft 产品生命周期。我建议您可以使用 Azure 管理 API,我们也可以使用api获取访问令牌。public static string GenerateAccessToken(string resource, string tenantId, string clientId,string secretKey)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var url = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var body = $"grant_type=client_credentials&client_id={clientId}&client_secret={secretKey}&resource={resource}";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HttpClient client = new HttpClient&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BaseAddress = new Uri(url)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StringContent content = new StringContent(body);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var result = client.PostAsync(url, content).Result;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var json = JObject.Parse (result.Content.ReadAsStringAsync().Result);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return json["access_token"].ToString();&nbsp; &nbsp; &nbsp; &nbsp; }如果你还想用经典的api,我也做了一个demo。请尝试以下代码。1.获取sastoken代码public static string GetSasToken(string resourceUri, string keyName, string key, TimeSpan ttl)&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var expiry = GetExpiry(ttl);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var sasToken = string.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return sasToken;&nbsp;}private static string GetExpiry(TimeSpan ttl){&nbsp; TimeSpan expirySinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1) + ttl;&nbsp; &nbsp;return Convert.ToString((int)expirySinceEpoch.TotalSeconds);&nbsp;}2.用c#代码创建规则。var serviceBusNamespace = "serviceBusNameSpace";var topicPath = "topicPath";var subscriptionName = "subscription name";var ruleName = "testrule2"; // rule namevar sharedAccessKeyName = "xxxSharedAccessKey",var key = "xxxxxxM2Xf8uTRcphtbY=";var queueUrl = $"https://{serviceBusNamespace}.servicebus.windows.net/{topicPath}/subscriptions/{subscriptionName}/rules/{ruleName}";var token = GetSasToken(queueUrl, sharedAccessKeyName,key ,TimeSpan.FromDays(1));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var body = @"<entry xmlns=""http://www.w3.org/2005/Atom"">&nbsp; &nbsp;<content type =""application/xml"" >&nbsp; &nbsp;<RuleDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<Filter i:type=""SqlFilter"">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<SqlExpression> type = 'REPLY' AND username = 'blabla@contoso.com' </SqlExpression>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</Filter>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</RuleDescription>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</content>&nbsp; &nbsp; &nbsp; &nbsp;</entry>";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var length = body.Length.ToString();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var content = new StringContent(body, Encoding.UTF8, "application/xml");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var _httpClient = new HttpClient();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _httpClient.DefaultRequestHeaders.Add("Authorization", token);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _httpClient.DefaultRequestHeaders.Add("ContentType", "application/atom+xml");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _httpClient.DefaultRequestHeaders.Add("Accept", "application/atom+xml");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; content.Headers.Add("Content-Length", length);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var requestResponse =&nbsp; _httpClient.PutAsync(queueUrl, content, new System.Threading.CancellationToken()).Result;测试结果:
打开App,查看更多内容
随时随地看视频慕课网APP