Many of our most recent projects here at Webigence are now being built on Microsoft’s very latest framework; .NET Core.
We’ve been following development of .NET Core closely (when it was still under the moniker of vNext) and began developing several new projects when the framework reached RC1 and have since migrated these projects to the latest RTM release.
This blog post won’t be going into much detail about getting started with .NET Core, more about the learning curves we’ve traversed and our experiences of using it. For getting started, I highly recommend reading articles from these excellent authors; Shawn Wildermuth, Scott Hanselman and Rick Strahl.
The challenge has been equal parts infuriating and rewarding but ultimately, totally worth it, as we’re going forward with the confidence that we know the major ins and outs of the framework.
Some of the more interesting challenges we have faced have been;
- Migrating between RC1, RC2 and RTM
- Managing service lifetimes
- Missing functionality
- Managing background threads
Migrating between RC1, RC2 and RTM
Since RC1, there have been a number of breaking changes between versions. Possibly most notably the move from the Dot Net Execution environment (DNX) to the .NET Core CLI and the many namespace changes. Generally speaking the migrations were painless, however I did find that there were additional steps I needed to take that I didn’t see in the .NET documentation and I ended up mashing together steps from different articles such as these:
- Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0
- Upgrading from RC1 to RC2
- Converting an ASP.NET Core RC1 Project to RC2
- Converting ASP.NET Core 1.0 RC2 to RTM Bits
- Notes about my [Bart Calixto] own experience migrating from RC1 to RC2
- Upgrading to ASP.NET Core RTM from RC2
Managing service lifetimes
One feature of .NET Core is baked in dependency injection and service lifetimes. At one stage of development we discovered that our UserManager class was using a different database context than our data access layer, as the service lifetime was configured as Scoped, i.e. it gets created once per request. This is on the recommendation of Microsoft;
Consider the following code to make a user an Admin in a system;
When we tried that transaction, we’d get the error “The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked”. Our prescribed fix was to get the user entity via the user manager, which uses its own context and avoids the tracking issue.
Entity Framework spatial types are a notable feature that we miss, however it is listed on the road map as high priority, so we’re looking forward to seeing these features added soon.
We have used EF spatial types before with success, and one of our new projects required us to perform searches for points within a given geography and calculating the distance between two points.
Since we could not use EF spatial types, we simply set up a stored procedure to do the work for us and added that in our repository. For example, a company would be set up with a geographic point (representing their operating base) and a service distance (a number in kilometres representing how far they would travel for work).
These variables would be used to create a geographic radius, representing their coverage area;
The result of STBuffer can be visually represented on a map;
Now, we can perform a search, by doing the following;
Which gives us the following companies whose operating boundaries are within our search!
Managing background threads
One of our projects required quite a lot of background processing. For example, adding a record to the system triggers a system event which;
- Sends an email notification
- Sends an SMS notification
- Sends the record to an API
These weren’t terribly long running tasks in their own right, but for the sake of performance and not tying up the main thread, we decided to push the processing of these actions onto a background worker task.
For this, we opted to use Hangfire, an easy to use background task manager. We have used Hangfire in the past, however, this was our first outing with implementing a .NET Core application. When we began the project the latest version (1.5.8 if you’re interested) did not have an official release supporting .NET Core, however since we were using a compatible framework, we were able to get it working with relative ease.
Since then we have upgraded to the latest version (1.6.2) which has official support and namespaces for .NET Core and has earmarked deprecations for the upcoming major release (2.0.0).
There were a few interesting changes due to the way .NET Core apps work. For example, graceful shutdown of the Hangfire server used to be handled in the Application_Stop() event in global.asax, however .NET Core introduces the IApplicationLifetime interface which can be used to register actions;
More about the IApplicationLifetime interface can be read about here.
Overall we are enjoying getting to know more about .NET Core CLI, the changes to the way .NET Core apps work and we’re looking forward to when Entity Framework spatial types are added as a feature soon.
At Webigence we keep up to date with the latest .NET technology and can implement Microsoft Azure (the flexible cloud computing platform) to help you “move faster, do more and save money”. Call us on 020 8739 0030 to talk about your web development requirements.
Blog written by Dave