According to the error information it means that request parameters error. I am not familar with mentioned api, you could share the link if possible.
But I recommand that you could use the Rules - Create Or Update. It is easy for us to use. For more information about service bus api, please refer to this document.
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
I also do a demo for it.
1) Get the access token
private static async Task<string> GetToken(string tenantId, string clientId, string secretKey)
{
var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
ClientCredential clientCredential = new ClientCredential(clientId, secretKey);
var tokenResponse = await context.AcquireTokenAsync("https://management.azure.com/", clientCredential);
var accessToken = tokenResponse.AccessToken;
return accessToken;
}
2) About how to get the tenantId ,clientId and secret key please refer to this tutorial. And don't forget assign to role the application.
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())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));
var body = "{\"properties\": { \"filterType\": \"SqlFilter\"},\"sqlExpression\": { \"sqlExpression\": \"myproperty=test\"}}";
HttpContent content = new StringContent(body);
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";
var response = httpClient.PutAsync(url, content).Result;
}
Test result

Update:
It seems the way I am creating the body is not correct:
Yes, you are right. According to your mentioned API document, we could know the body is xml format. But you xml code string is not xml format, you could vaild with xml validator online. There should be no space between charater <
/ >
and tags. For example < Filter i: type = ""SqlFilter"">
should be <Filter i: type = ""SqlFilter"">
But it is a classic rest api.
We’re no longer updating this content regularly. Check the Microsoft Product Lifecycle for information about how this product, service, technology, or API is supported.
I recommand that you could use the Azure manmagement API, we also could get access token with api.
public static string GenerateAccessToken(string resource, string tenantId, string clientId,string secretKey)
{
var url = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";
var body = $"grant_type=client_credentials&client_id={clientId}&client_secret={secretKey}&resource={resource}";
HttpClient client = new HttpClient
{
BaseAddress = new Uri(url)
};
StringContent content = new StringContent(body);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var result = client.PostAsync(url, content).Result;
var json = JObject.Parse (result.Content.ReadAsStringAsync().Result);
return json["access_token"].ToString();
}
If you still want to use the classic api, I also do a demo. please hava a try with following code.
1.Get sastoken code
public static string GetSasToken(string resourceUri, string keyName, string key, TimeSpan ttl)
{
var expiry = GetExpiry(ttl);
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = string.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
private static string GetExpiry(TimeSpan ttl)
{
TimeSpan expirySinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1) + ttl;
return Convert.ToString((int)expirySinceEpoch.TotalSeconds);
}
2.Create a rule with c# code.
var serviceBusNamespace = "serviceBusNameSpace";
var topicPath = "topicPath";
var subscriptionName = "subscription name";
var ruleName = "testrule2"; // rule name
var 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));
var body = @"<entry xmlns=""http://www.w3.org/2005/Atom"">
<content type =""application/xml"" >
<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>
</content>
</entry>";
var length = body.Length.ToString();
var content = new StringContent(body, Encoding.UTF8, "application/xml");
var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", token);
_httpClient.DefaultRequestHeaders.Add("ContentType", "application/atom+xml");
_httpClient.DefaultRequestHeaders.Add("Accept", "application/atom+xml");
content.Headers.Add("Content-Length", length);
var requestResponse = _httpClient.PutAsync(queueUrl, content, new System.Threading.CancellationToken()).Result;
Test Result:
