.NET Core

Get started with ABP framework on a Mac

In this post we’ll explore setting up the popular ABP framework for .NET Core on a Mac with a Postgres database.

In case you’re unaware, the ABP framework offers a number of out of the box features that can save a tremendous amount of time when starting a new web application. This includes a strong and opinionated architecture based on domain driven design, as well as multi-tenancy, theming and more.

Getting your environment setup

In this post we’ll explore getting the basic ABP app with Blazor up and running on a Mac.

Firstly, if you haven’t already done so download and install the latest .NET Core 5 SDK from Microsoft’s site.

Once installed you’ll want to add the ABP command line tools. These will allow you to quickly scaffold projects and code. This can be installed by opening the on your Mac, and running this line of code:

dotnet tool install -g Volo.Abp.Cli

If you’re running a more recent version of macOS – such as Big Sur – you’ll now be using ZSH by default instead of Bash in the Terminal app.

Try running the command abp --help. If you get a message stating that abp is not a known command, you may need to create a .zshrc file to allow you to access the ABP CLI from ZSH. Within Terminal, run the following commands:

  1. vi ~/.zshrc
  2. Paste export PATH=$HOME/.dotnet/tools:$PATH
  3. Run the command :wq to write the file to disk and quit
  4. Restart and you should be able to run abp --help

Creating the ABP project

Create a new folder called ToDoProject. Navigate to it from within Terminal, and run the following command:

abp new TodoApp -u blazor-server

This creates a new .NET Core solution based on the ABP framework.

If you’re on a Windows machine, normally you would now run the DbMigrator project to setup your database tables. However by default the ABP project uses LocalDB which is unavailable on the Mac.

As an alternative, you can use Postgres which IS available for the Mac.

The easiest way to install Postgres is to download and install the for free. Once launched, you can then install an app like Postico or use the command line to create a new Postgres database.

If using Postico, connect to your localhost Postgres server either via the server settings within Postico, or by double clicking the server from within the Postgres app.

Then, navigate to your server within Postico by clicking localhost in the top navigation bar. Click “+ Database” and add a new database called todoapp.

Click these buttons to setup the new database

Now we need to make some changes to the sample ABP app. Open the TodoApp.sln in your editor of choice (for the Mac this can include Visual Studio for Mac, Visual Studio Code or Rider).

Next replace the SQL package with Postgres. Add the Volo.Abp.EntityFrameworkCore.PostgreSql package via Nuget, and remove Volo.Abp.EntityFrameworkCore.SqlServer.

Then follow the rest of the steps in this article to update your project files to use the new Postgres package.

Lastly you’ll need to update the connection strings for your database.

Open src/TodoApp.Blazor/appsettings.json and update the following line to connect to your Postgres database, updating `<your username>` with your database username (for a Mac this is normally your Mac login username, unless you’ve specified a new user):

"ConnectionStrings": {
  "Default": "Server=localhost;Port=5432;Database=todoapp;User Id=<your username>/;Password="

Similarly, open src/TodoApp.DbMigrator/appsettings.json and update the same connection string:

"ConnectionStrings": {
  "Default": "Server=localhost;Port=5432;Database=todoapp;User Id=<your username>/;Password="

From within your IDE you should now be able to build and run your app, or from the Terminal app run dotnet run to see your first ABP web app running!

.NET Core

Understanding the Newtonsoft JSON Token

One of the concepts worth understanding when writing a custom converter for the popular Newtonsoft JSON framework is that of the JsonToken, and the role it plays in helping you understand the JSON being read.

The JsonToken documentation for Newtonsoft is relatively sparse – in part because once you understand it, it’s a relatively simple concept.

Effectively, when you’re attempting to deserialise a string representation of a JSON object, such as in the ReadJson method of a custom JsonConverter, the JsonToken represents each element or component (token if you prefer) of the object as it’s deserialised.

So for example, if you have the following JSON and implement the ReadJson method:

{	"message": "Hello world"}

When you first get the reader.TokenType value you’ll get JsonToken.StartObject back – this represents that the { implies that you’re first reading an object element.

If you were to then call reader.ReadAsync(), and then subsequently request the reader.TokenType again now you’ll get JsonToken.PropertyName in response. This is because the next element within the JSON string is the property name (in other words, the “message” key).

Lastly, if you were to call reader.ReadAsync() for a third time, you’d get back JsonToken.String as the value of the property is a string (“Hello world”). NewtonSoft will try and parse the value into a representation of a type – so for example, if that was a number, you’d get back Integer of Float, and if it was a Boolean you’d get back Boolean.

.NET Core

Throw or throw ex in C#?

One common question that comes up when working with exceptions in C#, is whether or not you should re-throw an existing exception by specifying the exception, or just using the throw keyword where an error occurs.

In most cases, it’s best to rethrow the existing exception, such as below:

try {	var networkResponse = await someNetworkService.GetAllPosts();}catch (Exception ex){	Log.Warning("An exception occurred", ex);	//Now lets rethrow this same exception	throw;}

By doing so, you ensure that the original stack trace for the exception is maintained. If you were to instead do something like this:

try {	var networkResponse = await someNetworkService.GetAllPosts();}catch (Exception ex){	Log.Warning("An exception occurred", ex);	//Now lets throw ex again	throw ex;}

You’ll now see that the exception stack trace only goes as far back as this line of code – not to the raw source of the exception.

In short, that’s why its normally better to just throw again, instead of specifying the exception when re-throwing.