This is very unintuitive, but to get Message Routing rules to work for any $body-based routing rules, you'll need to get the Payload to be rendered as JSON, not a string. But if you just follow instructions or tutorials, it'll be handled as a string. See - doing this: var TableName = "table01"; var PartitionKey = "key01"; string messagePayload = $"{{\\"tablename\\":\\"{TableName}\\",\\"partitionkey\\":\\"{PartitionKey}\\"}}"; using var eventMessage = new Microsoft.Azure.Devices.Client.Message(Encoding.UTF8.GetBytes(messagePayload)); await moduleClient.SendEventAsync(eventMessage); This will result in this: { "event": { "origin": "Simulator", "module": "ContosoModule", "interface": "", "component": "", "payload": "{\\"tablename\\":\\"table01\\",\\"partitionkey\\":\\"key01\\"}" } } Routing rules based on the payload - for example $body.tablename == "table01" will not work. Worse yet, even trying to do it properly and sending an object like this: JsonMessage newMsg = new JsonMessage() { tablename = "table01", partitionkey = "key01", }; string payload = JsonConvert.SerializeObject(newMsg); using var eventMessage = new Microsoft.Azure.Devices.Client.Message(Encoding.UTF8.GetBytes(payload)); await moduleClient.SendEventAsync(eventMessage); Might not work (well, it didn't for us). It's still a string, not JSON. However, adding this should help: eventMessage.ContentEncoding = Encoding.UTF8.ToString(), eventMessage.ContentType = "application/json" When the content type of the message is properly configured as application/json, it should render successfully. And with that, it should look like this: { "event":{ "origin":"Simulator", "module":"ContosoModule", "interface":"", "component":"", "payload":{ "tablename":"table01", "partitionkey":"key01" } } }