Friday, 12 August 2022

Could not load file or assembly 'System.Runtime, Version 6.0.0.0' with .Net Core

 It’s the story of couple of days back, where as usual I deployed my application on Azure App Service after testing it locally and then I was surprised when the application was not running as expected.

Since everything works locally so there were no reason to believe of any error on cloud environment too so I just do a google search and found lot of links related to this error but unfortunately none of them related to the problem I had. So with couple of my cool collogues, I started trouble shooting on this issue, and this is what all I did until I was able to drill down to the root cause.

  1. Tried to get the actual cause by running the dll from Azure App Service => Console option, and it tells me the error as above screenshot. 
  2. Deployment of the application to the Azure App Service was happening through CI/CD pipeline So I thought there could be something wrong going in there hence tried the deployment through visual studio to App Service and modified the appsettings.production.json through App Service => App Service Editor option (at the time of this article this feature is on Preview) manually.
    And result, it works then what the hell is going wrong with CI/CD deployment, and still no clue.
  3. Tried the application to local IIS deployment and it worked here too. Oh my God.
  4. After spending hours a random thought occurred, With the working application deployed in local IIS, I replaced the appsetting.Production.json file locally by copying it from Azure App Service => App Service Editor option (to use the one deployed to azure and created by CI/CD process).

Finally here I got some relief as issue was reproducible with local env and familiar too. Hence started debugging and While debugging I found that the issue was with below code throwing exception due the keyVaultUrl value is set to Empty character.

builder.Configuration.AddAzureKeyVault(
new Uri(keyVaultUrl),
new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
...
}),
new PrefixKeyVaultSecretManager(prefix));

So what was happening here is, In production, application was not using Azure Key Vault but the code was there and tried to build the configuration with AzureKeyValut and ending up throwing exception while starting the application.

CI/CD was creating the appSettings.Production.json and in this process it was replacing the keyvalut related setting to “ “ an empty character and this was the culprit.

Before I found this issue, it was looking huge but after I found it, I felt like Ahk!what the hell.

So if you ever encountered such error with production, My first recommendation would be to run the application locally with the same configuration and appsettings.json or web.config used in deployment/production and save your time. Sometime google also won’t be able to help you unless some people like me share his/her crazy experiences like this.

I too had no plan to share this :) until I got the below feedback from one of my reader for similar crazy issue related to docker networking.

Thank You All for such a beautiful feedback which turns as fuel for people like me to share more and more even it seems to be silly sometime.

Hope you enjoyed the content, follow me for more like this and please don’t forget to like/comment for it. Happy programming.

Wednesday, 3 August 2022

CI/CD with GitHub Actions to deploy Application to Azure App Service

 This is a follow up article of my previous article published here as CI/CD with GitHub Actions. There I was talking about basics of creating a GitHub action to automate project build and run tests.

"ConnectionStrings": {
"ConnectionString": "#{ConnectionString}#",
},

Note: Please follow my previous article if are new to GitHub Actions.

jobs:
build:
runs-on: windows-latest
environment: Production
steps:
- uses: actions/checkout@v2

- name: Replace token for appsettings.Production.json
uses: cschleiden/replace-tokens@v1.1
with:
tokenPrefix: '#{'
tokenSuffix: '}#'
files: '["src/DemoAPI/appsettings.Production.json"]'
env:
ConnectionString: ${{secrets.CONNECTION_STRING}}
      - name: Set up .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
#include-prerelease: true

- name: Build projects
run: |
dotnet build src/DemoAPI/DemoAPI.sln --configuration Release

- name: Publish Project
run: |
dotnet publish src/DemoAPI/DemoAPI.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp
- name: Upload artifact for deployment job
uses: actions/upload-artifact@v2
with:
name: .net-app
path: ./myapp
deploy:
runs-on: windows-latest
needs: build
environment:
name: 'production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v3
with:
name: .net-app
path: upload_artifact
- name: Deploy to Azure Web App
id: deploy-to-webapp
uses: azure/webapps-deploy@v2
with:
app-name: 'DemoAPI'
slot-name: 'production'
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: upload_artifact

CI/CD with GitHub Actions

 If you are working with GitHub Actions, you might too get confused with the term Workflow vs Actions. Here I’m gonna explain the difference as well as also giving you example to create your first CI/CD, even if you have never done it before.

Workflow is all the tasks which has to be performed when the event (in our case, push event on the branch repo) occurs.

name: Build and Run tests#define variables
env:
DOTNET_VERSION:'6.0.x'

An Event is something that happens in a GitHub repository. i.e. Push, Create, delete, deployment, fork, pull_request, workflow_dispatch etc.

name: Build and Run tests#define variables
env:
DOTNET_VERSION:'6.0.x'
on:
push:
branches:
- master
workflow_dispatch:

Job is a series of steps inside the workflow which are executed. Each step is either a script to be executed or an action that would run.

name: Build and Run tests#define variables
env:
DOTNET_VERSION:'6.0.x'
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build:
environment: Test

The Runners are the process on the server that runs the workflow. Runners are hosted in the cloud and we specify the name of the runner for job using runs-on syntax.

name: Build and Run tests#define variables
env:
DOTNET_VERSION:'6.0.x'
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
environment: Production
name: Build and Run tests#define variables
env:
DOTNET_VERSION:'6.0.x'
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
environment: Production
steps:
- uses: actions/checkout@v2
- name: Set up .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Build projects
run: |
dotnet build --configuration Release
- name: Test with the dotnet CLI
run: dotnet test

Bonus

Follow me here for my next article on CI/CD with GitHub Actions to deploy Application to Azure App Service