I’m trying to construct an Azure ServiceBus Subscription Rule that will have either a correlation filter or sql filter depending on the length of param’s subjectFilter
array property. I tried this using if
with union
, based on this answer. However, it looks like the object is constructed with all properties. For example, the sql filter errors with "At least one system or user property must be set for a correlation filter."
Here’s my code (simplified).
- The copy variable contains properties to use for each subscription name and
filterProperties
, with defines afilterType
and is used as the baseproperties
object. - It also declares a separate object for the
sqlFilterProperties
andcorrelationFilterProperties
, respectively. - Either the
sqlFilterProperties
orcorrelationFilterProperties
object should be unioned with thefilterProperties
to construct the completeproperties
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string"
},
"topics": {
"type": "array"
},
"subscriptionName": {
"type": "string"
}
},
"variables": {
"apiVersion": "2018-01-01-preview",
"copy": [
{
"name": "subscriptions",
"count": "[length(parameters('topics'))]",
"input": {
"name": "[concat(parameters('resourceName'), '/', parameters('topics')[copyIndex('subscriptions')].name, '/', parameters('subscriptionName'))]",
"filterProperties": {
"filterType": "[if(greater(length(parameters('topics')[copyIndex('subscriptions')].subjectFilter),1),'sqlFilter','correlationFilter')]"
},
"sqlFilterProperties": {
"sqlFilter": {
"sqlExpression": "[concat('sys.subject in (''',join(parameters('topics')[copyIndex('subscriptions')].subjectFilter,''','''), ''')')]",
"requiresPreprocessing": false
}
},
"correlationFilterProperties": {
"correlationFilter": {
"subject": "[parameters('topics')[copyIndex('subscriptions')].subjectFilter[0]]",
"requiresPreprocessing": false
}
}
}
}
]
},
"resources": [
{
"type": "Microsoft.ServiceBus/namespaces/topics/subscriptions/rules",
"apiVersion": "[variables('apiVersion')]",
"copy": {
"name": "subscriptionFilters",
"count": "[length(parameters('topics'))]"
},
"name": "[concat(variables('subscriptions')[copyIndex()].name, '/subject')]",
"properties": "[union(variables('subscriptions')[copyIndex()].filterProperties, if(startsWith(variables('subscriptions')[copyIndex()].filterProperties.filterType, 'sql'), variables('subscriptions')[copyIndex()].sqlFilterProperties, variables('subscriptions')[copyIndex()].correlationFilterProperties) )]"
}
]
}
2
Answers
I got this answer from Microsoft through a support ticket. The problem is
subject
metadata property is actually calledlabel
when creating filters. (In C# it is calledSubject
.) So simply changing the sqlExpression to usesys.Label
and the correlationFilter properties to useLabel
solved the problem.See docs
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messages-payloads
https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.servicebus.message.label?view=azure-dotnet
Rather than using the
union
method directly, you can conditionally assign the filter properties based on thefilter
type. Compare the filter type with'correlationFilter'
or'sqlFilter'
using theequals
function.You can make the changes listed below to your code and try deployment once again.
Alternatively, you can also use system properties like (ContentType, Label, MessageId, ReplyTo) and user-defined values to filter, when you use the
CorrelationRuleFilter
default constructor. Use theIDictionary string, object
> property Properties to supply user-defined properties for the correlation filter as detailed here.