Hi all,
I want to streamline my deployments, and have therefore created a PowerShell script that deploys an ARM template to Azure, and then have some output parameters that I would like to use to do the following:
My problem is the final step - When creating Steps - An error is returned.
First off, here is my PowerShell script - I'll explain my steps afterwards:
# Perform deployment
$deploymentOutput = az deployment group create --name $deploymentName --resource-group $resourceGroup --template-file ".\$deploymentFolder\azuredeploy.json" --parameters ".\$deploymentFolder\azuredeploy.parameters.$environmentName.json" --output json | ConvertFrom-Json
# Check deployment output structure
if ($deploymentOutput -and $deploymentOutput.properties -and $deploymentOutput.properties.outputs -and $deploymentOutput.properties.outputs.'ServiceBus-PrimaryKey' -and $deploymentOutput.properties.outputs.'ServiceBus-PrimaryKey'.value) {
$confirmation = Read-Host "Do you want to register a webhook within Dataverse? (yes/no)"
if ($confirmation -ne "yes") {
Write-Host "`nDeployment complete - Webhook skipped."
exit
}
# Extract necessary values
$primaryKey = $deploymentOutput.properties.outputs.'ServiceBus-PrimaryKey'.value
$serviceBusName = $deploymentOutput.properties.outputs.'ServiceBus-Name'.value
$keyVaultName = $deploymentOutput.properties.outputs.keyvaultName.value
# Retrieve secrets from Key Vault
Write-Output "`nRetrieving secrets..."
$secrets = @{}
@('CRM-ClientId', 'CRM-Secret', 'CRM-TenantId', 'CRM-Endpoint') | ForEach-Object {
Write-Host -NoNewline "."
$secrets[$_] = (az keyvault secret show --vault-name $keyVaultName --name $_ --query "value" -o tsv)
}
$clientId = $secrets['CRM-ClientId']
$clientSecret = $secrets['CRM-Secret']
$tenantId = $secrets['CRM-TenantId']
$dataverseUrl = $secrets['CRM-Endpoint']
# Define Dataverse environment URL and authentication profile name
$envName = "PAC-$environmentName"
# Authenticate to Dataverse using PAC CLI
#Write-Output "`nAuthenticating PAC"
#pac auth create --environment $dataverseUrl --tenant $tenantId --applicationid $clientId --clientSecret $clientSecret --name $envName
# Get access token using Azure AD App details
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body @{
client_id = $clientId
client_secret = $clientSecret
scope = "$dataverseUrl/.default"
grant_type = "client_credentials"
}
$accessToken = $tokenResponse.access_token
$webhookName = "Integration-ServiceBUS"
$serviceBusUrl = "sb://$serviceBusName.servicebus.windows.net"
# Check if the webhook already exists
$existingWebhook = Invoke-RestMethod -Method Get -Uri "$dataverseUrl/api/data/v9.2/serviceendpoints?`$filter=name eq '$webhookName'" -Headers @{
Authorization = "Bearer $accessToken"
}
# Define the payload for the webhook registration
$webhookPayload = @{
messageformat = 2
name = $webhookName
contract = 6
authtype = 2
saskeyname = "DataverseSender"
saskey = $primaryKey
namespaceaddress = $serviceBusUrl
solutionnamespace= $serviceBusName
description = "Service Endpoint for ServiceBUS"
path = "crm-contact-changed"
namespaceformat = 2
} | ConvertTo-Json -Depth 10
# Either PATCH existing or POST new
if ($existingWebhook.value.Count -gt 0) {
Write-Output "Service Endpoint already exists - Patching"
$serviceEndpointId = $existingWebhook.value[0].serviceendpointid
Invoke-RestMethod -Method Patch -Uri "$dataverseUrl/api/data/v9.2/serviceendpoints($serviceEndpointId)" -Headers @{
Authorization = "Bearer $accessToken"
"Content-Type" = "application/json"
"If-Match" = "*"
} -Body $webhookPayload
Write-Output "Webhook updated successfully."
} else {
Write-Output "Service Endpoint was not found - Creating new"
Invoke-RestMethod -Method Post -Uri "$dataverseUrl/api/data/v9.2/serviceendpoints" -Headers @{
Authorization = "Bearer $accessToken"
"Content-Type" = "application/json"
} -Body $webhookPayload
Write-Output "Webhook created successfully."
}
} else {
Write-Output $deploymentOutput
Write-Output "`nThe expected output structure is not present. Please check the deployment output."
}
My ARM template creates a ServiceBus, a Key Vault and other resources. After creation I get some output parameters, among those is the ServiceBus endpoint, ServiceBus name and Key Vault name. And that is used by the PowerShell script to create the ServiceEndpoint.
Using Plugin Registration Tool (PAC Tool PRT) I am able to see my ServiceEndpoint:
However when I try to create the SdkMessageProcessingSteps I have the following PayLoad:
{
"supporteddeployment": 0,
"stage": 40,
"statuscode": 1,
"customizationlevel": 1,
"description": "Integration-ServiceBUS: Update of contact",
"statecode": 0,
"rank": 1,
"asyncautodelete": true,
"name": "Integration-ServiceBUS: Update of contact",
"solutionid": "fd140aae-4df4-11dd-bd17-0019b9312238",
"ismanaged": false,
"versionnumber": 332817509,
"mode": 1,
"introducedversion": "1.0",
"canbebypassed": false,
"filteringattributes": "firstname,lastname",
"enablepluginprofiler": false,
"componentstate": 0,
"canusereadonlyconnection": false,
"eventexpander": null,
"configuration": null,
"category": null,
"plugintypeid@odata.bind": "/plugintypes(ef521e63-cd2b-4170-99f6-447466a7161e)",
"sdkmessageid@odata.bind": "/sdkmessages(20bebb1b-ea3e-db11-86a7-000a3a5473e8)"
}
The PluginTypeId is Microsoft.Crm.ServiceBus.ServiceBusPlugin (found by querying
And SdkMessageId is "Update":
However the error I get is this:
{
"error": {
"code": "0x80040256",
"message": "Action failed for assembly 'Microsoft.Crm.ServiceBus, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35': No publisher is found, assembly must be registered in isolation."
}
}
So if anyone has created the Steps through API - Any help would be appreciated.
I am able to create the step in Plugin Registration Tool (not through XRM toolkit):
But not by REST Api
I finally found my missing parameter, on the following article: https://devblogs.microsoft.com/ise/registering-plugins-in-dataverse/ there was a description of fields necessary.
And my missing parameters was :
"eventhandler_serviceendpoint@odata.bind":"/serviceendpoints(a1842d7d-6e36-ef11-8409-7c1e521fb863)",
"sdkmessagefilterid@odata.bind": "/sdkmessagefilters(83c9bb1b-ea3e-db11-86a7-000a3a5473e8)",
The EventHandler is the ServiceBus reference, and the SDK message filter Id is the Entity I wish to subscribe to - In this case "Contact".
So my final payload to register the Step is:
{
"name": "Integration-ServiceBUS: Update of contact",
"description": "Integration-ServiceBUS: Update of contact",
"eventhandler_serviceendpoint@odata.bind":"/serviceendpoints(512414c1-7434-ef11-8409-000d3ab2c00a)",
"sdkmessageid@odata.bind": "/sdkmessages(20bebb1b-ea3e-db11-86a7-000a3a5473e8)",
"plugintypeid@odata.bind": "/plugintypes(ef521e63-cd2b-4170-99f6-447466a7161e)",
"sdkmessagefilterid@odata.bind": "/sdkmessagefilters(83c9bb1b-ea3e-db11-86a7-000a3a5473e8)",
"supporteddeployment": 0,
"asyncautodelete": true,
"filteringattributes": "firstname,lastname",
"rank": 1,
"stage": 40,
"statuscode": 1,
"mode": 1
}
And this creates my much wanted Processing Step on my ServiceEndpoint
The final deployment will be part of a managed solution.
However, I would like to create the ServiceEndpoint - And Plugin Steps through API to do it at the same time as my ARM template is deployed. After creation it will be added to the solution, which will then be deployed onto production as managed.
@Ruprect If you are trying to do this for deployment reasons via the Web API, I would recommend deploying the ServiceEndpoint and SDK Message Processing Step as part of a managed solution deployment instead. This way the objects will be in a managed state.
@parvezghumra Originally I used a licenced user in Plugin Registration Tool, and an App Registration in Postman, but I have also tried with the same licensed user in Postman - To no avail.
It might be some part of the payload I've missed, but if I remove the plugintypeid@odata.bind or the sdkmessageid@odata.bind I get a missing parameter error:
{
"error": {
"code": "0x80040200",
"message": "plugintypeid is missing."
}
}
@Ruprect Are you using the same user account to register the SDK Message Processing Step via the Web API as you do when you're doing it using the Plugin Registration Tool? Does that user have System Administrator privileges?
stampcoin
17
mmbr1606
15
Super User 2025 Season 1
ankit_singhal
11
Super User 2025 Season 1