Building .NET Core WebJob Console App CI/CD Using Azure DevOps Pipelines
Get some hands-on experience with constructing a .NET Core WebJob application and deploying it through an Azure DevOps pipeline.
Join the DZone community and get the full member experience.
Join For FreeWebJobs is a feature of Azure App Service that enables you to run a program or script in the same context as a web app, API app, or mobile app according to this Microsoft document.
If you build your WebJob Console app in a .NET Framework then it's very easy to build and deploy the WebJob with the parent API or Web App by linking it to Web/API App as shown below:


The above linkage of the WebJob console application with parent Web/API app is not supported by design in .NET Core. So what do we do?
In this article, we are going to see how we can build a .NET Core WebJob Console app separately from the parent Web/API app, and deploy under the existing parent Web/API App using Azure DevOps Build and Release pipeline.
Build Pipeline - Build the .NET Core Console App
To build a .NET Core console app we need to perform four basic build tasks in the Azure DevOps build pipeline.
dotnet restore
dotnet build
dotnet publish
- Publish build artifacts to drop location
Azure Web Job supports the following file types only:
- .cmd, .bat, .exe
- .ps1 (using PowerShell)
- .sh (using Bash)
- .php (using PHP)
- .py (using Python)
- .js (using Node.js)
- .jar (using Java)
Since we are in .NET core, we are expecting a .exe file as the output for our console app. If you build your .NET core app just by running dotnet build
it will generate a .DLL filebut not a .EXE file. To generate a .EXE file as build output use the following arguments in the publish
step
--configuration $(BuildConfiguration) --self-contained -r win10-x64 --output $(build.artifactstagingdirectory)
The argument --self-contained -r win10-x64
will make the difference here, as this will generate an .EXE file out of the build.
Next, the Enable Zip Published Projects
option. This will create a ZIP file out of your build output.
Once it's been published to a ZIP folder is completed, we need to drop this ZIP file to a Drop Location. Use $(Build.ArtifactStagingDirectory)
as path to publish. Use any artifact name of your choice. In this example, the artifact name is webjobs_drop
Release Pipeline - Deploy the Build Artifact to Azure App Service
Upon running the Build Pipeline you will get your build output in webjobs_drop/.zip
location.
To deploy this to any existing Web/API App's WebJob running in Azure App Service we have to run an Azure PowerShell script task to achieve this.
We are going to use KUDU Zip Deploy API
to deploy the build output to the app service. This will unpack the Zipped build output to wwwroot\App_Data\Jobs\\
folder.
To setup the release pipeline we need to create an empty pipeline with the following pipeline variables
resourceGroupName
- Resource Group name of your applicationscheduleName
- Contentious/ Triggered. In this example it's ContinuousscmApiUrl
- SCM Api Url. Example: https://.scm.azurewebsites.net/apiwebJobName
- your webjob name. Your code will be deployed under wwwroot\App_Data\Jobs\scheduleName\webJobName folderzippedArtifactPath
- zipped artifact path of your build output file

Once the variables are set up, we need to do the following:
- Add a
Azure PowerShell script task
- Select the Azure Connection type
- Select the Azure Subscription where your WebApp is located
- Select Script Type as Inline Script
In the Inline Script editor add the below PowerShell script:
#Zipped artifact path - get the path from Azure DevOps Pipeline variables
$path = "$(System.DefaultWorkingDirectory)\$($env:zippedArtifactPath)"
#Test the path if exists
if (-not (Test-Path $path))
{
throw [System.IO.FileNotFoundException] "$($path) not found."
}
#Resource type and details
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$($env:webAppName)/publishingcredentials"
#Get the Publishing Profile details
$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $($env:resourceGroupName) -ResourceType $resourceType -ResourceName $resourceName -Action list -Force
#Creating the Auth Token using user name and password from Publish profile credentials
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName,$publishingCredentials.Properties.PublishingPassword)))
#Get the file from the Build Artifacts path
$files = Get-ChildItem -Path $path -Recurse
Test-Path -Path $files[0]
#Authentication Header
$authHeader = " Basic " + $base64AuthInfo
#Kudu Zip Deploy API URL
$deployUrl = "$($env:scmApiUrl)/zip/site/wwwroot/App_Data/jobs/$($env:scheduleName)/$($env:webJobName)/"
#Invoke Kudu Zip Deploy API to deploy the WebJob
$contentType = "multipart/form-data"
$userAgent = "powershell/1.0"
$ZipHeaders = @{
Authorization = $authHeader
}
$response = Invoke-RestMethod -Uri ([System.Uri]::new($deployUrl)) -Headers $ZipHeaders -UserAgent $userAgent -Method PUT -InFile $files[0] -ContentType $contentType
Write-Host "Deployment Successful"
This PowerShell script will get the publishing profile details of your web app and use this information to login to KUDU ZipDeploy API to upload your Zipped build output to the desired location.
The deployment location is defined as
SCM API URL https://<>.scm.azurewebsites.net/api/zip
plus virtual directory path site/wwwroot/App_Data/jobs/<continuous/triggered>/
Accessing Environment-Specific Configuration
The above build and release pipeline will build and generate a .EXE file for your .NET Core Console application and deploy the build output to the Azure App Service Virtual directory. There may be scenarios where your WebJob may need to read some environment-specific configurations. In such cases, you have to add environment-specific appsettings.json
files as appsettings.json
To read values from Environment specific JSON files, we can rely on ASPNETCORE_ENVIRONMENT
variable. This variable can be set manually from the Azure Portal or while deploying the Parent WebApp/API app using Azure release pipeline in the app settings section.
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
Console.WriteLine("Environment Variable: " + environmentName);
var env = hostingContext.HostingEnvironment;
Console.WriteLine("hostingContext.HostingEnvironment: " + env.EnvironmentName);
config.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables().Build();
});
Add the above code in your Program.cs
file to read the environment-specific values from appsettings.json
files.
Wrap Up
To summarize we have performed the following actions:
dotnet publish
with--self-contained -r win10-x64
argument, which generates the WebJob supported EXE file.- Zipped the build artifact directory.
- Used
KUDU ZipDeploy
API to publish the WebJob console application to the wxisting web/API App Virtual directory usingAzure PowerShell Script
task.
I hope this article will help you to navigate through your .NET Core WebJob dev/deploy journey with Azure DevOps build release pipeline.
Published at DZone with permission of Subhankar Sarkar. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments