Deploying .NET Core app using a custom Kudu script
With the recent release of .NET Core 3 and the even more recent announcement of .NET Core 3.1 LTS, I felt now was a good time to move iambacon blog over from the .NET framework to the new world of .NET.
As part of the update, I wanted to separate the CMS from the blog. iambacon is an MVC web app and the CMS part of it was an Area within the app. I'm not a fan of Areas, I don't have a good argument against them, I used Areas in this app to see if it would change my mind, it didn't. So I've created a new ASP.NET Core web app and migrated the CMS to that.
Azure deployment
I deploy my blog to Azure using Git. It is simple and straightforward. I have a custom Kudu deployment script as I also compile Sass and run unit tests. I'm very happy with it and do not feel the need to change to say Azure DevOps.
Deploying a .NET Core app
There is a custom deployment script generator for Kudu called Kudu Script, which will generate a script for you. The example given on the wiki page is
kuduscript -y --aspWAP pathToYourWebProjectFile.csproj -s pathToYourSolutionFile.sln
There are two options:
- --aspWAP: ASP.NET web application (path to the .csproj file)
- -s: path to the .sln file
This will create a deploy.cmd
script with the following for the CMS app.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------
echo Handling .NET Web Application deployment.
:: 1. Restore NuGet packages
IF /I "src\IAmBacon\IAmBacon.sln" NEQ "" (
call :ExecuteCmd nuget restore "%DEPLOYMENT_SOURCE%\src\IAmBacon\IAmBacon.sln"
IF !ERRORLEVEL! NEQ 0 goto error
)
:: 2. Build to the temporary path
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
call :ExecuteCmd "%MSBUILD_PATH%" "%DEPLOYMENT_SOURCE%\src\IAmBacon\IAmBacon.Admin\IAmBacon.Admin.csproj" /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="%DEPLOYMENT_TEMP%";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\src\IAmBacon\\" %SCM_BUILD_ARGS%
) ELSE (
call :ExecuteCmd "%MSBUILD_PATH%" "%DEPLOYMENT_SOURCE%\src\IAmBacon\IAmBacon.Admin\IAmBacon.Admin.csproj" /nologo /verbosity:m /t:Build /p:AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\src\IAmBacon\\" %SCM_BUILD_ARGS%
)
IF !ERRORLEVEL! NEQ 0 goto error
:: 3. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
)
Running the script will fail with this error:
error MSB4041: The default XML namespace of the project must be the MSBuild XML namespace. If the project is authored in the MSBuild 2003 format, please add xmln s="http://schemas.microsoft.com/developer/msbuild/2003" to the
<Project>
element. If the project has been authored in t he old 1.0 or 1.2 format, please convert it to MSBuild 2003 format.
This because Kudu Script has generated a script for a .NET web application, not a .NET Core web application.
Unfortunately the example in the wiki is for the old .NET apps and does not mention .NET Core at all.
Generating the right script
Run kuduscript --help
to get the list of options.
There are several options the one we’re interested in is
--aspNetCore <projectFilePath>
Create a deployment script for ASP.NET Core web application, specify the project file path
Swap --aspWAP
for --aspNetCore
.
kuduscript -y --aspNetCore pathToYourWebProjectFile.csproj -s pathToYourSolutionFile.sln
This time the deployment script will contain
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------
echo Handling ASP.NET Core Web Application deployment.
:: 1. Restore nuget packages
call :ExecuteCmd dotnet restore "%DEPLOYMENT_SOURCE%\src\IAmBacon\IAmBacon.sln"
IF !ERRORLEVEL! NEQ 0 goto error
:: 2. Build and publish
call :ExecuteCmd dotnet publish "%DEPLOYMENT_SOURCE%\src\IAmBacon\IAmBacon.Admin\IAmBacon.Admin.csproj" --output "%DEPLOYMENT_TEMP%" --configuration Release
IF !ERRORLEVEL! NEQ 0 goto error
:: 3. KuduSync
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
Running the script will build and publish successfully.
Summary
Kudu is a simple way to deploy apps to Azure using Git. Kudu allows custom deployment scripts which are simple to generate however using the correct options is essential. It's a shame the wiki does not give a .NET Core example but hopefully this article has helped fill in the blanks.