Blazor routing and Navigation

Routing

If you take a look at the generated pages for a Blazor application, you’ll see the following

@page "/counter"

this denotes a route to our page, i.e. http://localhost:44319/counter.

Note: When you compile your application a file is generated (see Counter.g.cs in compiled folder) and this page declaration is converted to a RouteAttribute.

You can have multiple routes pointing to the same page, in this example all these routes will navigate to the same Counter.razor page

@page "/counter"
@page "/mycounter"
@page "/something"

Probably more useful is the ability to add parameters to our routes, for example

@page "/counter"
@page "/counter/{InitialValue}"

By default InitialValue is of type string, but we can change this by using a constraint, for example

@page "/counter"
@page "/counter/{InitialValue:int}"

Now we simply create a property in our code with the ParameterAttribute applied to it, like this

[Parameter]
public int? InitialValue { get; set; }

We use a nullable int in case the value is missing. We can also have routes handling different type contraints (for example a string or on int) to mean two different things

@page "/counter"
@page "/counter/{InitialValue:int}"
@page "/counter/{SomeString}"

In our OnInitialized() method (part of the component life cycle) we might then set the currentCount to InitialValue.

The routes are declared in our pages but the routing component itself can be found in App.razor. In this case the Router will locate the routes from the supplied AppAssembly

<Router AppAssembly="@typeof(Program).Assembly">

We can also includes routes within AdditionalAssemblies, for example maybe you’ve got some reusable components with routing supplied, hence we write

<Router AppAssembly="@typeof(Program).Assembly" 
   AdditionalAssemblies="new[] { typeof(MyComponents).Assembly }>

Navigation

If you want to navigate to other pages, we need to use the NavigationManager. This needs to be injected into our page, using

@inject NavigationManager NavManager

Now to navigate, for example when a button is click, we use the following

NavManager.NavigateTo("counter/2");

In the instance we’ll navigate to the relative URL/page with “counter/someData”.

This works fine when navigating to other pages but if we want to navigate within a page and we’re using the component’s OnInitialized method to initialize data?

Because OnInitialized is called when the page is initial loaded and because we’re already in the page, this method will not normally be called again if we navigate within the page, so we simply need to supply an extra parameter to our NavigateTo code to force the page to reload, i.e.

NavManager.NavigateTo("counter/2", true);

Note: An alternative solution ofcourse is to override the other life cycle method OnParameterSet and instead move initialization code to that method.

Visual Code debugging in Chrome

I’m using Visual Code for my React development and I’m using Chrome as my browser – I want to debug my React code in Chrome using Visual Code, so let’ see how it’s done.

First off, check out Introducing Chrome Debugging for VS Code, secondly VS Code – Debugger for Chrome.

Or, if you prefer, here’s the steps

  • Ctrl+Shift+X within Visual Code to load the Extensions list
  • Search for Debugger for Chrome and install it (if not already installed)

You’re going to need a launch.json file in the .vscode folder, here’s a minimal example

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "Launch Chrome",
            "url": "http://localhost:3000",
            "webRoot": "${workspaceFolder}"
        },
        {
            "type": "chrome",
            "request": "attach",
            "name": "Attach to Chrome",
            "port": 9222,
            "webRoot": "${workspaceFolder}"
        }
   ]
}

In the above we have two configurations, both for Chrome, one launches Chrome with the supplied URL, the second attaches to an existing instance of Chrome.

If you now choose the option Run | Start Debugging, Chrome will launch with your URL loaded. You can place breakpoints in your code (before or after you start debugging) and you’re application will break at these breakpoints as you’d expect and you can inspect variables etc. So basically a full debugging experience.

Default commands within debug mode are as follows

  • F5 Continue
  • F10 Step Over
  • F11 Step Into
  • Shift+F11 Step Out
  • Ctrl+Shift+F5 Restart
  • Shift+F5 Stop

To attach to an existing running instance of Chrome, ensure you start Chrome with the following command line parameters –remote-debugging-port=9222, for example create a shortcut link with Target “C:\Program Files\Google\Chrome\Application\chrome.exe” –remote-debugging-port=9222.

You’ll also need to ensure only this instance of Chrome is open/running and then you can run the “Attach to Chrome” option.

Adding imports to your Blazor app.

The default template’s supplied for Blazor Server and WebAssembly applications, gives you lots upfront. However, ofcourse you’re likely to want to import further functionality via the @using directive.

For example, let’s say we want to add the following to the Counter.razor IncrementCount method (from the default template generated files)

Debug.WriteLine("Increment");

We can simply add the following to the top of the Counter.razor file

@using System.Diagnostics

Alternatively and especially useful for using code across multiple pages/components, you can put the above code into the _Imports.razor file. Think of this as a global set of using reference, but only for @code sections, for standard C# classes we ofcourse use the using directive as usual.

Note: I’ve found my current version of Visual Studio doesn’t seem to immediately recognise the updated _Imports.razor file, a build fixes that.

Getting started with Blazor on Server and WebAssembly

As of Visual Studio 16.6.3 and .NET core 3.1.301 there’s now support for create Blazor applications for Server and WebAssembly.

Creating your project

From Visual Studio

  • Create a new project and look for the Blazor App template
  • You’ll be presented with the options to create a Blazor Server App or Blazor WebAssembly App

From the dotnet CLI

  • To create a server app run
    dotnet new blazorserver -o your-app-name
    
  • To create a WebAssembly app run
    dotnet new blazorwasm -o your-app-name
    

You can also run the generated code by changing directory to the your-app-name and then execute the following

dotnet run

Whichever route you took to generate your Blazor app. When you run the application, you can access the application via https://localhost:5001/.

Blazor Server

I’m not going to cover Blazor on the server specifically, as this is very much like Blazor WebAssembly crossed with ASP.NET core development. Basically what you write for WebAssembly is very much the same as you’d write for the Server.

There are benefits and downsides to Blazor Server and Blazor WebAssembly, I’m not going to list them all (because I’m sure I’ll forget one or two) but basically running Blazor on the server gives faster start-ups, allows us to be more secure with our source code (in that the code is not available to be downloaded but runs instead on the server). However the Server implementation suffers from the lack of an offline mode (i.e. PWA is supported via Visual Studio for Blazor WebAssembly) and there’s bound to be more network traffic with a server implementation.

Blazor WebAssembly

WebAssembly or WASM is a binary instruction set for browsers (well those that support it). Think of it as a virtual machine for running byte code. The important parts of WASM are that any it can run code generated from C# (other languages are adding support) instead of just using JavaScript for the Web. The second thing of interest is that the virtual machines are sandboxed.

It might sound like we’ve sort of been here before, and we have to a degree, but this time we have an open standard instead of plugins, Java applets, Silverlight or ActiveX.

With Blazor WebAssembly the compiled code is executed on the client, within the browser as a SPA. With Blazor Server, much like ASP.NET, the code comes from the server, however clever use of SignalR allows diffs to/from the DOM to be sent back and forth in an efficient manner.

Looking into the Blazor templates

If we look at both the WASM and Server code we’ll see our pages written in Razor syntax, here’s the Counter.razor file

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Razor syntax is denoted by the @ prefixed commands, for example @page is basically a routing command to this counter page. @code is a C# code block. Also we can use variables from our code by prefixing with the @ (such as @currentCount).

When you see a @code block, think of it as a class, hence in this example we have a field currentCount and a member method named IncrementCount.

Binding

One way binding is very simple (and shown in the above snippet)

<p>Current count: @currentCount</p>

In this case the variable is updated via the @code and one way binding ensures that the text in the HTML is updated automatically for us.

Ofcourse we’re going to need two-way binding and this is pretty simple in Blazor. Let’s add an input to the Counter.razor code (just place above the button HTML).

<input @bind="currentCount" />

This input will by default, bind the variable currentCount to it’s value property, we can also write explicit code for this in this way

<input @bind-value="currentCount" />

You use the syntax @bind-{Property} replacing {Property} with whatever the property or attribute name is that you wish to bind to.

What happens now is that, when the user changes the input value and the control loses focus, the currentCount is automatically set to the new value. We may want to instead have the value update as the input changes, in this instead we use @bind-value:event, for example

<input @bind-value="currentCount" @bind-value:event="oninput"/>

Note: if you put a char or string into the input, the binding doesn’t update and hence you get no exceptions or anything.

Blazor Components

Each page that we have is basically a Blazor component, but we can create a component that’s not a page – in other words it’s just a component and will be used to render HTML fragments.

From Visual Studio, right mouse click on the Shared folder and then select Add | Razor Component. Mine’s named Count.razor and the aim is to move the code into it’s own component

<p>Current count: @currentCount</p>

I called my component Count.razor. Let’s change the Counter.razor page to use this new component, so replace the code and above with

<Count @bind-Counter="currentCount"></Count>

Here’s our Count.razor component code

<p>Current count: @Counter</p>

@code {
    [Parameter]
    public int Counter { get; set; }

    [Parameter]
    public EventCallback<int> CounterChanged { get; set; }
}

Whilst we’re not using the CounterChanged event, it’s required for the binding code. The ParameterAttribute is basically exposing properties to the parent components or pages, i.e. for use outside of the component itself.

Now I’m not 100% on this code (i.e. CounterChanged not being used) as it worked fine, but I was finding Visual Studio displays error tildes under the currentCount usage in the Counter page, although everything worked. I’m not sure if this is just an issue where Visual Studio it not yet upto date with all the syntax or a mistake on my part – although it does work.

However, if we just change the page’s code to

<Count @bind-Counter="currentCount" 
   @bind-Counter:event="CounterChanged"></Count>

then no error tildes were displayed in Visual Studio – this needs further investigation as it seems a bit superfluous adding this event when it’s not used – but hey, I’m new to Blazor!

That’s it for Getting Started.

References

Razor syntax reference for ASP.NET Core
WebAssembly
Introduction to ASP.NET Core Blazor

Getting started with GitHub and the .NET Core Action

GitHub actions allows us to add workflows to our projects.

In the previous three posts we looked at using Appveyor, Circleci and Travis CI to create our CI/CD pipelines, now let’s look at using GitHub Actions.

  • From your GitHub project, select the Actions tab
  • GitHub kindly lists a suggested workflow, so as my project is in C# it suggests a .NET Core build action, select Set up this workflow if it suits your needs (it does for this example)
  • You’ll now get to edit the Actions yml configuration, I’ll accept it by clicking Start commit and this will add the dotnet-core.yml to .github/workflows. Just click commit to add it to your repository.
  • From the Actions | .NET Core workflow, press the Create status badge, then Copy status badge Markdown and place this markdown into your README.md

Note: If you’re using the .NET Core workflow and using multi targets (i.e. <TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks> then you may find the build failing because the .NET 4.7.2 frameworks is not installed.

The process described above, demonstrated that we have a YML based DSL for creating our workflow, checkout Workflow syntax for GitHub Actions.

Let’s take a look at a workflow file for one of my projects – in this case .NET core was not suitable, instead I wanted .NET Framework

name: .NET Core

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup MSBuild Path
      uses: warrenbuckley/Setup-MSBuild@v1
      
    - name: Setup NuGet
      uses: NuGet/setup-nuget@v1.0.2
     
    - name: Restore NuGet Packages
      run: nuget restore MyApplication.sln
 
    - name: Build
      run: msbuild MyApplication.sln /p:Configuration=Release /p:DeployOnBuild=true

The name is what you’ll see in your list of GitHub actions (via the GitHub project’s Actions tab/button, this workflow monitors pushes and pull requests on master and then has a list of jobs to undertake once this workflow is triggered.

We’re going to run this workflow on Windows as the project is a .NET framework application. The steps of the workflow specify the “parts” required to build and test the project, so require the checkout action and Setup-MSBuild, setup-nuget libraries. Then we run the nuget restore to get all nuget package then build the application.

Note: I’ve not include tests as yet on this workflow, so I’ll leave that to the reader.

As usual we’ll want to create a badge, in the Actions tab in GitHub, select the workflow and on the right of the screen is a button Create status badge. Click this then press the Copy status badge Markdown button and this will place the Markdown into your clipboard. Here’s an example of mine

![.NET Core](https://github.com/putridparrot/MyApplication/workflows/.NET%20Core/badge.svg)

Getting started with Travis CI and GitHub

As I’m seemingly trying out each free tier CI/CD online service I can, let’s look into Travis CI.

  • Create an account, with you preferred authentication provider (from the one’s they have available)
  • Sign-in, if not done so already
  • We need to click on Activate All Repositories using GitHub Apps
  • Then click Approve & Install. You can select specific repos. if you wish before click on this button
  • You’ll be asked to sign in again this will take you to GitHub where you click Authorise travis-pro if you wish to continue
  • You’ll then be redirected to Travis CI

Let’s get started

In your project’s repository add the file .travis.yml an example is shown below

language: csharp

branches:
  only:
  - master

If you’ve read the previous posts, you won’t be surprised to see another .yml file with the Travis CI DSL. If we take a look at Building a C#, F#, or Visual Basic Project we can see that the language for the .travis.yml is csharp for .NET languages C#, F# and VB.NET.

Here’s my .travis.yml for an F# .NET core project

language: csharp
mono: none
dotnet: 3.1
solution: FSharp.Health.sln

script:
  - dotnet build
  - dotnet test

Pretty straight forward, we use the script section for the steps to run the dotnet commands to build and test our code.

Ofcourse we’ll want to add a build badge to the README.md, so from the build within Travis CI simply click on the build badge next to your project name, then select FORMAT Markdown. Here’s an example for my FSharp.Health project

[![Build Status](https://travis-ci.com/putridparrot/FSharp.Health.svg?branch=master)](https://travis-ci.com/putridparrot/FSharp.Health)

Getting started with Circleci and GitHub

In my previous post I talked about using CI/CD along with GitHub and in that post we concentrated on Appveyor. Let’s now look at one of the alternatives, Circleci.

As you’d expect, you need to create an account and I used GitHub authentication as I wanted this CI/CD application working with my GitHub projects. It’s probably not a requirement but certainly everything integrated nicely (I’ve not yet seen if that differs with alternative repositories hosts).

Once you’ve created your account you’ll need to install the Circleci application within GitHub – I actually don’t recall the process but I suspect there’s an “Install Application” button or the likes.

Let’s get started

Due to the GitHub integration you’ll see a list of your projects. Simply press the Set Up Project button. That’s pretty much all there is to it to get started, but we’re probably going to want to customise the process.

In your project’s repository add the file config.yml into the .circleci folder, as below

.circleci/config.yml

This allows us to write the configuration for our Circleci build pipeline using a DSL. Here’s one for an F# project I have in Circleci

 version: 2.1

 orbs:
  win: circleci/windows@2.2.0

 jobs:
   build:
     executor: win/default     
    
     steps:
       - checkout
       - run: dotnet build
       - run: dotnet test Image.Processing.Tests

In this case we’re using the 2.1 (see CircleCI 2.1 Configuration Reference Guide.

The first thing we do (after setting the version of the DSL) is to map to an orb definition. In this case we’re using a predefined orb, we can actually create our own orbs if needed (but we’re not going there at the moment, or maybe ever, we’ll have to wait and see).

Note: An orb is a shareable package of configuration, see Explore Orbs for a whole bunch of different orbs..

Now we supply the jobs. In this case a build job using win/default, basically a Windows image.

Next we set up the build steps. These are self-explanatory, as you’d expect, we need to checkout our code, build the code and then run our tests. There’s a checkout step, the rest can be thought of as simply commands to run.

We’re now going to want to add a badge to the README.md in our project to allow us and others to see the status of our build.

Unlike Appveryor (unless I’m missing something, in which case I’ll update this post later) there’s no copy & paste option for the badge link, instead have a look as Adding Status Badges, here’s the template

[![<ORG_NAME>](https://circleci.com/<VCS>/<ORG_NAME>/<PROJECT_NAME>.svg?style=svg)](<LINK>)

So for my F# Image.Processing project this looks like the following

[![putridparrot](https://circleci.com/gh/putridparrot/Image.Processing.svg?style=svg)](https://circleci.com/gh/circleci/circleci-docs)

At this time, I’m not sure how to link to the specific build (or whether this is possible), I ‘ll add to this post in the future if I find it’s possible.

Note: If you prefer, change style=svg to style=shield for a different looking status image.

That should get you started.

Getting started with Appveyor and GitHub

I wanted to add some CI/CD (more CI than CD) to some of my GitHub projects. There’s several options available for this, including online or on-prem. Two seemed to catch my eye on other GitHub repositories, Appveyor and Circleci.

Both offer free plans which, as you’d expect, have some limitations. However for the most part these are things that don’t matter too much to my projects, i.e. you may be limited to public repositories only (hence they’re supporting OSS), probably only run a single build at a time etc.

Let’s get started

The application we’re going to look into here is AppVeyor.

Simply create an account and I used GitHub authentication to sign in – seemed logical as I was ultimately wanting this to integrate into GitHub.

Once you’ve signed in you’ll be presented with an Install button to install their app. into your GitHub space – I assume this is how it works, I’ve not looked into it further, either way this hooks into your repo. changes and triggers your project’s build.

Next up you go to the Project option in the Appveyor UI and select New Project. To be honest all is pretty obvious. Now with the GitHub integration you’ll get a list of available projects from your GitHub account.

Select Add and you’re done! Well sort of…

You may need to make some configuration changes, either within the Appveyor UI or better still (imho) via their DSL.

All you need to do is add a file named appveyor.yml. Here’s a simple example for a .NET project

version: 1.0.{build}

image: Visual Studio 2019

build:
  verbosity: minimal

before_build:
- cmd: nuget restore

Checkout the appveyor.yml reference for more information.

Basically what we’ve done in the above yml, is created a a build version, this will be displayed within the Appveyor UI when you inspect builds. Next we’ve stated what image we want to use to build our project, obviously Visual Studio 2019 is specified for my .NET projects.

The build can be set to quiet, minimal, normal or detailed. For now mine is minimal.

Finally I’ve added a pre-build step (before_build) and listed the command nuget restore. This was because for the projects I’ve tried, I have to update the nuget packaged first.

We’re not specifying the branches, but we can add a whitelist of branches that should be part of the build like this

branches:
  only:
    - master
    - production

By default Appveyor detects whether there’s tests and can run these automatically, but you might prefer to set a custom test step. For example I found an F# project ran tests fine locally but failed on Appveyor, adding the following solve this (here I’ve specified the assembly to test)

test_script:
- cmd: dotnet test FSharp.Units.Tests

Next up we’ll want to have a badge in our README.md so we can see the state of our build or better still, others can see the state of our build. If you select the project’s settings and then the Badges option, there’s a sample markdown code section where you can just copy the markdown and place in your README.md and it’ll show the build status in a nice little indicator.

Here we’ve looked at the basics for setting up a build with the DSL. Obviously this is a great way of doing things, but whilst setting up your DSL it means for every change, you need to commit and push then wait for the build to complete to see if everything works. In Appveyor you can go to the Setting | General option of your project and click Ignore appveyor.yml and instead set everything up in the Appveyor UI. Then you can go to the Settings | Export YAML option to generate your configuration.

That should get you started.

Converting old style csproj to new style sdk

This tool’s pretty good for converting the old style csproj files to the new SDK style.

Just install using

dotnet tool install --global Project2015To2017.Migrate2019.Tool

Now navigate to where your solution is (that you want to convert) and from the command prompt run

dotnet migrate-2019 wizard "D:\Path\To\My\TestProject.sln"

You’ll be asked if you want to backup things and whether you want to migrate, answer Y to the migrate question (backing up is up to you). This will then locate all the csproj’s in the solution and convert them.

Tests are failing with DateTime expected format

I’m creating some builds on appveyor for some of my GitHub projects and hit a small snag. All of the DateTime’s in my tests have test data in the en-GB format, i.e. dd/MM/yyyy.

Note: Whilst I haven’t checked, I suspect appveyor is hosted on en-US machines.

A simple way to resolve this is, just add a NUnit SetUp that converts the current culture to the expected culture, i.e.

SetUp]
public void SetUp()
{
   var culture = new CultureInfo("en-GB");
   Thread.CurrentThread.CurrentCulture = culture;
   Thread.CurrentThread.CurrentUICulture = culture;
}