Blazor client side application and DigitalOcean App Platform

Blazor is a technology I have been thinking of testing out for a while, but I did not find time for it before. Now I am going to make a simple little application that can calculate the commission payment for me. Since DigitalOcean also recently announced DigitalOcean Apps, I will see how it will be to deploy a simple static application to their service for hosting.

Requirements

On the requirements side of things, it is not that much. I downloaded the newest Dotnet CLI (for me that was dotnet 3.1) and an editor of choice. For the editor, I use Visual Studio Code. I also use Github for the source code that also will be useful when I should deploy the application to the DigitalOcean App Platform.

Getting started writing the code

The first thing I did was to open my terminal and navigate to the location where I wanted my project. Then creating a directory for the Blazor application.

$ mkdir payment-calculation && cd payment-calculation
$ mkdir src && cd src
$ mkdir payment-calculation && cd payment-calculation
$ dotnet new blazorwasm
$ code .

For my simple calculator application, I was creating a form with the different inputs that I needed. To get the two-way binding, I found out that I had to use the @bind-value="" and @bind-value:event="oninput". Only using the @bind="" was just doing a one-way binding.

<div class="form-row">
    <div class="col-md-3 md-3">
        <label for="minimumsalary">Årlig fastlønn</label>
        <input type="number" class="form-control" id="minimumsalary" @bind-value="YearlySalary" @bind-value:event="oninput" required>
    </div>
    <div class="col-md-3 md-3">
        <label for="invoicedhours">Fakturerte timer</label>
        <input type="number" class="form-control" id="invoicedhours" @bind-value="HoursInvoiced" @bind-value:event="oninput" required>
    </div>
    <div class="col-md-3 md-3">
        <label for="hourrate">Timelønn</label>
        <input type="number" class="form-control" id="hourrate" @bind-value="HourRate" @bind-value:event="oninput" required>
    </div>
    <div class="col-md-3 md-3">
        <label for="commission">Provisjon</label>
        <div class="input-group mb-2">
            <div class="input-group-prepend">
                <div class="input-group-text">%</div>
            </div>
            <input @bind-value="CommissionProcent" @bind-value:event="oninput" type="number" class="form-control" id="commission" placeholder="Provisjon">
        </div>
    </div>
    <div class="col-auto">
        <button class="btn btn-primary mb-2" @onclick="CalculateCommission">Kalkuler</button>
    </div>
</div>

I just added all the code in an @code block and the private method is used on the calculate button in the html.

@code {
    private bool ShowResult { get; set; } = false;
    private int YearlySalary { get; set; }
    private int HoursInvoiced { get; set; }
    private int HourRate { get; set; }
    private int CommissionProcent { get; set; }
    private double MonthlySalary => YearlySalary / 12;

    private double MonthlyPayment { get; set; } = 0.0;
    private double EstimatedYearlyPayment { get; set; } = 0.0;

    private void CalculateCommission() {
        var selfCost = MonthlySalary*1.5;
        var invoicedTurnover = HoursInvoiced * HourRate;

        MonthlyPayment = invoicedTurnover;
        EstimatedYearlyPayment = MonthlyPayment*12;
        ShowResult = true;
    }

When I was playing around with Blazor, I started the application using dotnet run and open the url in Chrome. When I continued making changes and relaunching the site, I could not see the new changes. Looks like Chrome is caching the webassembly really well, so I needed to clear site data quite often in the Chrome developer tools.

Pushing source code to Github

First, it is good practiced to create a .gitignore file. I use the website gitignore.io and type Visual Studio and Visual Studio Code to get those. Then I create a .gitignore file and paste the content from the website to that file and save the file.

# In the root directory of the project
$ touch .gitignore

To be able to push the source code to a git repository at Github, I logged in to my Github account and created a new repository. Then I copied the SSH url for the repository and went to the terminal. I made sure that I had the current working directory in the root directory of the project and then executed some command to be able to initiate a local git repository and then make a first commit.

$ git init .
$ git add .
$ git commit -m "First commit"

Then I realized that Github now use main as the default branch instead of master, so I had to create a local branch main and I then deleted the master branch.

$ git chechout -b main
$ git branch -D master

Now it is time to connect the local git repository to the remote repository at Github and setup that the local branch main is tracking the remote branch main. That is done with the -u parameter in the command.

$ git remote add origin <GITHUB rebpsitory url>

Deploying to DigitalOcean App Platform

To deploy to DigitalOcean App platform, I had to connect connect my Github repository to the process and chose which branch that should be deployed. That means that I needed to publish the application and have push the published artifacts to a own branch. I made a Google search and found some people doing this to be able to publish to Github pages, but the process is the same. I then had to setup a simple Github Action that publish every time I pushed to the main branch.

Publish with Github Action

Create a directory .github in the root of the repository and a subdirectory workflows in that directory. Then I created a workflow file ci.yaml. Look in the linked blog post above to see how you can setup a Github secret with the personal access token that is needed.

name: 'Publish application'
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
        # Checkout the code
        - uses: actions/checkout@v2

        # Install .NET Core SDK
        - name: Setup .NET Core
          uses: actions/setup-dotnet@v1
          with:
            dotnet-version: 3.1.x

        # Generate the website
        - name: Publish
          run: dotnet publish src/payment-calculation/payment-calculation.csproj --configuration Release

        # Publish the website
        - name: GitHub Pages action
          if: ${{ github.ref == 'refs/heads/main' }}
          uses: peaceiris/actions-gh-pages@v3.6.1
          with:
            github_token: ${{ secrets.PUBLISH_TOKEN }}
            publish_branch: release
            publish_dir: src/payment-calculation/bin/Release/netstandard2.1/publish/wwwroot
            allow_empty_commit: false
            keep_files: false
            force_orphan: true

What this workflow do us to checkout the repository and setup the .Net Core SDK that I am using. Then I run the dotnet publish command in release mode. Then I use the Github action for Github pages, but since I am publishing static website just another place, this is fine to use. I then push the artifacts to a branch release.

Continue with deploying to DigitalOcean App platform

DigitalOcean guided me through connecting my Github account and giving DigitalOcean permission to see the repository with the code that I was about to deploy. When I had been giving DigitalOcean access, I was at step 1.

At the first step of the process, I just selected the repository with my Blazor app code. Since I only gave permission to this repository, the drop down just contained one option.

At the second step, I could give the application a name and choose a region. In Europe, I could choose Frankfurt or Amsterdam. Since I already have other resources in Amsterdam, that was my choice. Then I needed to pick with branch that should be deployed. Here I had to pick the release branch, since that is the branch the Github workflow is pushing the published application into.

In step 3, there was not that many options, I was deploying a static site and kept with that and pressed next.

In the last step, I could pick a plan. I wanted it to be free, so I wanted the starter plan and launched the application.

On the last page, I could see the deployment process and be able to redeploy if I wanted that. I could also go to the live application. The deployment to the DigitalOcean App platform was straight forward for a static website. My website is live on this url and my code is in a public Github repository.

Teis Lindemark

Read more posts by this author.