I’m currently trying to publish an Azure Managed App in the Azure Marketplace, and one of the issues I’ve encountered is deploying the code for my Azure functions and web apps.

First, let me show you the structure of the zip file that I submitted for certification.

- createUiDefinition.json
- mainTemplate.json
- nestedtemplates (folder)
   - webapi.json

When I first looked in the samples from Github I saw that I have to supply a package URI which should be a .zip file with my published artifacts. However, after a few days the certification process failed because I wasn’t allowed to point the packageUri property to an external location. Instead, I had to add the code inside the zip file along with my json files.

Thankfully, the reviewiers pointed me to the right documentation and I was able to figure out what to do, so I’ll describe the steps in here as well.

It seems that you are allowed to also deploy scripts or artifacts, but you have to follow some rules.

1. Create a zip file of your published app

In my case, I just had to download the artifact generated by my Azure DevOps pipeline, but you can also do it manually if you use the command “dotnet publish” and zip the contents of the “publish” folder.

2. Add the published app inside the zip file

In the root I only have the “createUIDefinition.json” and “mainTemplate.json” files, this is the recommended approach. That’s why I created an “artifacts” folder where I placed my published app, so now the structure looked like this:

- createUiDefinition.json
- mainTemplate.json
- nestedtemplates (folder)
   - webapi.json
- artifacts (folder)
   - webapi.zip - this is a zip file with the contents of the "binReleasenet5.0publish" folder

3. Point the packageURI property to the location of the zip file

In order to do this we have to allow 2 parameters in the mainTemplate.json file, they are called “_artifactsLocation” and “_artifactsLocationSasToken”. DO NOT change their name, because they are automatically initialized during deployment and if you change the name like I did initially then it won’t work.

This is how you add them in the parameters of the mainTemplate:

"parameters": {
        "_artifactsLocation": {
            "type": "string",
            "metadata": {
                "description": "The base URI where artifacts required by this template are located including a trailing '/'"
            "defaultValue": "[deployment().properties.templateLink.uri]"
        "_artifactsLocationSasToken": {
            "type": "securestring",
            "metadata": {
                "description": "The sasToken required to access _artifactsLocation.  When the template is deployed using the accompanying scripts, a sasToken will be automatically generated. Use the defaultValue if the staging location is not secured."
            "defaultValue": ""

4. Build the URI of the zip file

With these two parameters you can then create a variable that contains the location of the zip file:

"zipUrl": "[uri(parameters('_artifactsLocation'), concat('artifacts/webapi.zip', parameters('_artifactsLocationSasToken')))]"

As you can see, I use the _artifactsLocation as the base URI, then I concatenate the location of the zip file and the SAS token.

5. Use the zipUrl in the deployment of your web api

    "type": "Extensions",
    "apiVersion": "2021-01-01",
    "name": "MSDeploy",
    "dependsOn": [
        "[resourceId('Microsoft.Web/Sites/', variables('appServiceName'))]",
        "[resourceId('Microsoft.Web/Sites/config', variables('appServiceName'), 'connectionstrings')]"
    "properties": {
        "packageUri": "[variables('zipUrl')]"
    "condition": "[not(equals(variables('zipUrl'), ''))]"

Now your code will be deployed in the app service that you created.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.