![]() |
From .NET Core in Action by Dustin Metzgar
Learning a new development framework is a big investment. You need to learn how to write, build, test, deploy, and maintain applications in the new framework. As a developer, there are many frameworks to choose from and it’s difficult to know what’s best for the job. Even if you’re currently developing software with .NET, .NET Core is different enough that you’ll need to spend time learning the tools and techniques to use it properly. To understand why .NET Core is worth a look,it helps to know where you’re starting from. |
Save 37% on .NET Core in Action. Just enter code fccmetzgar into the discount code box at checkout at manning.com.
Why .NET Core?
If you’re a .NET Framework developer
.NET Core is for some Framework components a reboot, and for others a chance to work cross-platform. Becausethe .NET Framework was built mostly in managed (C#) code, those portions don’t need code changes to move to .NET Core. Libraries that depend on Windows-specific componentsmust be removed or refactored to use cross-platform alternatives. The same would apply to your applications.
Your .NET apps can be cross-platform
Your existing .NET Framework applications can work on other operating systems. This is great for library authors who want to expand their audience, or developers who want to use the same code in other areas of a distributed application. Even if you want to develop in .NET on your shiny new MacBook without having to dual boot to Windows.
Not all of the Framework has been ported to .NET Core, but major portions have. Some API differences exist. For example, if you use a lot of reflection, you may need to refactor your code to work with Core. See the “Differences from the .NET Framework” section below for more information. That’ll help you determine if it’s feasible to port to Core.
ASP.NET Core outperforms Framework ASP.NET
The difference in performance between ASP.NET Core and Framework ASP.NET is several orders of magnitude. Much of ASP.NET was restricted by the legacy System.Web library. The .NET Framework supports older versions of ASP.NET projects, and that constraint has restricted ASP.NET’s evolution. With Core, Microsoft decided to rewrite the whole stack. This means breaking changes, but the gains are worth the effort of migrating.
.NET Core is the focus for innovation
Backwards compatibility is a double-edged sword. It means your application can continue to be supported with newer versions of the Framework, which is a popular feature. A lot of effort goes into making sure that changes made in new releases of the Framework won’t break existing applications. This isn’t the case one hundred percent of the time, but it’s close.
All the effort to avoid breaking changes restricts innovation in the Framework. Changes to the Framework need thorough justification (usually from customers), exhaustive testing, and approval from many levels of product groups. I’ve been in meetings where people argued over one- or two-line code fixes –which caused me to reconsider my life choices.
With .NET Core, it’s easier for a team to work on their library independent of the core libraries. Changes to core libraries, like System.Collections, still require the same vigor as with the .NET Framework, but it’s easier for ASP.NET Core or Entity Framework Core to make substantial changes without being constrained by backwards compatibility. This allows for greater innovation.
The .NET Framework ships as one whole product,but Core is broken up into pieces. Developers can now choose which version of a library they want to use, as long as it’s outside the .NET Standard Library, and .NET Core teams can innovate with less difficulty. This is why, in the future, you’ll see only bug fixes going to the Framework; Core gets all the new features.
Release cycles are faster
If you’ve ever encountered a bug in the Framework and reported it to Microsoft, you’re aware of how long it takes for a fix to be released. The Framework has long release cycles, usually measuring at least a year, and there are tiny windows during these cycles for feature work. Each code change can cause issues in unexpected places elsewhere in the Framework. To give each team enough time to test the framework, there are many times when code changes are restricted or heavily scrutinized. If you found a bug in .NET, you’re better off finding a workaround than waiting for an update.
.NET Core follows a much faster release cadence. Developers can use nightly builds to test early. Libraries that aren’t part of the .NET Standard Library can release at their own pace. Becauseeverything is open source, any developer can propose a fix if Microsoft doesn’t respond quickly enough. If the fix isn’t accepted, the discussion is held in public in order thateveryone can see why that decision was made
If you’re new to .NET
On Windows platforms, the .NET Framework didn’t have much competition. Microsoft could make changes to everything from the OS kernel layers up through the high-level .NET libraries. By taking .NET to other platforms, the playing field has changed. .NET must now compete with all the other development frameworks out there. Here are some things that set .NET apart.
C# is an amazing language
The flagship language of .NET, C#, has many distinguishing features, such as Language Integrated Query and asynchronous constructs,which make it powerful and easy to use. C# also continues to innovate. The C# team designs the language openly because they want anyone to make suggestions or participate in the discussion. The compiler (Roslyn) is entirely modular and extensible. I recommend picking up a book called C# in Depth by Jon Skeet to learn more.
ASP.NET Core performance is on par with the top web platforms
If you’re writing web applications or services, ASP.NET Core is a great platform to build with. It has excellent performance and a low memory footprint. Many features can make your applications more capable and easier to develop and maintain. I’ll cover more on ASP.NET Core later.
.NET Core is not starting from scratch
.NET has been around since before 2000. The Framework code has been hardened over the years and its developers have benefitted from the experience. Much of the Framework code that has been ported to Core is untouched. This gives .NET Core a head start in terms of having a reliable framework to build applications. .NET Core is also completely supported by Microsoft. Support can be a blocker for some organizations to adopt open source software. This decreases the risk of using Core for your applications.
What is .NET Core?
To understand .NET Core, it helps to understand the .NET Framework. Microsoft released the .NET Framework in the early 2000s. The .NET Framework is a Windows-only development framework that, at its lowest level, provides memory management, security, exception handling, and many other features. The .NET Framework comes with an extensive set of libraries that perform all kinds of functions, from XML parsing to HTTP requests. It also supports several languages and compiles them into the same common intermediate language; any language can use a library built in any other language. These key concepts are also present in .NET Core.
In 2016, Microsoft acquired Xamarin and released .NET Core 1.0. Xamarin had previously ported large parts of the .NET Framework to run on Linux/Unix-based operating systems. Some of the code could be shared between the .NET Framework, Xamarin, and the new .NET Core, but the compiled binaries couldn’t. Part of the effort of .NET Core was to create a standardized platform that allowed all .NET implementations to share the same libraries.
Figure 1 .NET Framework, .NET Core, and Xamarin all share the same standardized platform called the .NET Standard Library
Xamarin and the .NET Framework were previously silos where binaries couldn’t be shared between them. With the introduction of the .NET Standard Library and the common infrastructure, these two frameworks are now part of a unified .NET ecosystem.
What is .NET Core? In the figure above, it appears that .NET Core is another framework that includes UWP (Universal Windows Platform) and ASP.NET Core. In order to make .NET Core a reality, the authors created the .NET Standard Library and the common infrastructure. .NET Core is all three of these things.
Key .NET Core features
.NET Core borrows the best from the .NET Framework and incorporates the latest advancements in software engineering. These are a few of the distinguishing features of .NET Core.
Expand the reach of your libraries
With .NET Core, you can write your application or library using the .NET Standard Library.
Then it can be shared across many platforms.
Figure 2 .NET Core development
The same library can work in your backend service ‘on-premise’ or in the cloud, and in your client application running on a cell phone, tablet, or desktop. Instead of building separate apps for iOS, Android, and Windows, you can build one app that works on all platforms. .NET Core is small and perfect for use in containers, which scale easily and reduce development time.
.NET Core and the .NET Standard Library establish a common platform. In the past, when a new version of an operating system or a new device came along, it was the responsibility of the developer to rebuild their application or library for that new platform and distribute the update. With .NET Core, there’s no need to rebuild and redistribute. As long as the new platform supports all of your dependent libraries, it supports your application.
Simple deployment on any platform
Microsoft products tend to have complex installation processes. COM components, registry entries, special folders, GAC – all are designed to take advantage of Windows-only features. The .NET Framework relies on these constructs, which makes it unsuitable for other operating systems.
When shipping an application that relies on the .NET Framework, the installer has to be smart enough to detect if the wrong .NET Framework version is installed and provide a way for the user to get the right one. Most modern Windows versions include the .NET Framework. This makes certain applications easier to install, but can cause complications if the application uses features that aren’t installed by default, such as ASP.NET integration with IIS or WCF components.
Another complication comes from patches. Patches that include bug fixes or security updates can be distributed to customers via Windows update or through the Microsoft Download Center. The .NET Framework you test your application on may have different patches from the ones customers are using. It‘s often difficult to determine what causes strange behaviors in an application when you assume that the .NET Framework is the same for all customers.
.NET Core’s modular design means that you only include the dependencies you need. All of those dependencies go into the same folder as your application. Deploying an application is as simple as copying a folder. Another advantage to this approach is you can have multiple versions running side-by-side. This strategy is key to making the deployment experience consistent on all platforms.
Clouds and containers
In cloud systems, it’s important to drive for higher density toserve more customers with less hardware. The smaller the footprint of an application, the higher the density. Virtual machines have been prevalent in clouds for years, but they’ve several problems:
- Size – A typical virtual machine file is gigabytes, if not tens of gigabytes. This makes them time-consuming to transfer across networks and have significant requirements on disk space.
- Startup times – Starting a virtual machine means starting an operating system. For Windows, this presents a challenge because of the time it takes to start a new machine. This can make handling sudden bursts in traffic difficult.
- Memory – The virtual machine needs to load an entire operating system into memory, along with the applications. This means a lot of a host’s memory is wasted.
- Inconsistency – The same virtual machine can be copied to multiple hosts, and the hosts have to provide the same virtualized hardware, which can be dependent on the physical hardware. There’s no guarantee that a virtual machine will operate the same, if at all, on any given host.
Containers solve the issues of virtual machines by virtualizing the operating system. The container only holds the application and its dependencies. File sizes are many times smaller, startup times are in seconds, only the application’s loaded in memory, and the container’s guaranteed to work the same on any host.
The .NET Framework, being built-in to Windows, can’t be run on containers. Given the clear advantage of containers, one of the design decisions of .NET Core was to make it modular. This means that your .NET Core application can be “published” in a way where it and all of its dependencies are in one place, which is easy to put into a container.
ASP.NET performance
In case you’re unfamiliar with ASP.NET, it’s the web application platform built into the .NET Framework. ASP.NET is used by many high-profile organizations, including Stack Overflow. ASP.NET was released in 2002 with the first version of the .NET Framework, and has continued to evolve. Despite its success, there was a feeling among the ASP.NET team that they were losing developers because ASP.NET performance isn’t competitive and it only works on the Windows platform.
A company called TechEmpower runs a benchmark of web application platforms every few months and provides a ranking divided into several categories. The benchmarks are run on Linux, and Windows-only platforms weren’t included. For the ASP.NET team, this was troubling. Many platforms are out there for writing web applications that are cross platform, and their performance numbers are impressive. Plus, some Java frameworks were posting astronomical numbers, such as undertow with 5.7 million plaintext requests per second or netty with 4.9 million.
Figure 3 TechEmpower benchmark, round 12
On round eleven of the TechEmpower benchmark, ASP.NET MVC on the Mono platform was included in the testing. The results weren’t good. ASP.NET on Mono produced a paltry 2,000 plaintext requests per second. Mono wasn’t created by Microsoft, and it wouldn’t have received the same amount of performance tuning as the regular .NET Framework. To get a fairer comparison, the ASP.NET team decided to run a benchmark with .NET 4.6 on the same hardware as TechEmpower. The result was around 50,000 requests per second. Still not even close to NodeJS (320,000 requests per second), or any of the other top frameworks on the TechEmpower list.
The pitifully low score wasn’t a surprise. As mentioned before, the ASP.NET team knew some of the hurdles that stood in the way of being competitive with frameworks like NodeJS. Hurdles that could only be cleared by rewriting the whole thing. That’s exactly what happened.
The ASP.NET team embarked on building ASP.NET Core, and many months later the team celebrated crossing the one million requests per second mark. As of this writing, ASP.NET Core produces around four million plaintext requests per second on the Tech Empower benchmark hardware. A team dedicated to pushing that number further, as well as improving the performance of many other real-world scenarios, was formed.
ASP.NET Core is indicative of a shift in Microsoft’s thinking. Microsoft realizes it has to be competitive to win developers. It also has to compete on platforms other than Windows. This was the driving force behind the creation of .NET Core.
Open source
Modern software developers aren’t content to ask for a feature and hope it gets delivered in the next release, which could be a year away. When there’s already an open source project that fulfills their needs this is particularly true. As large companies warm to open source software, even the most faithful Microsoft developers turn to other frameworks and libraries to get their own projects done on time and within budget. If Microsoft cared about “developers, developers, developers” they have to make a change.
Exposing the source for the .NET Framework was the first step. The .NET Framework source code has been publicly available for years at referencesource.microsoft.com and also on GitHub.
Figure 4 .NET Framework reference source
It’s quite different to go from exposing the source to accepting external contributions. The .NET Core developers not only wanted to allow external contributions, but they wanted to include the community in the design and development. This led to a lot more transparency. Every week, the ASP.NET Core team holds a live community standup meeting at http:// live.asp.net. The code for .NET Core has been available publicly on GitHub from the start, and anyone can make a pull request. Community members can create bugs and feature requests in GitHub. .NET Core has marked a significant change in direction for Microsoft regarding open source.
Differences from the .NET Framework
.NET Core isn’t only the .NET Framework for Linux and Mac. Rather than port all of the .NET Framework, Microsoft has taken the approach of waiting to see what customers want. There has to be enough customer interest in a framework feature to persuade Microsoft to allocate the resources to do a port. One of the obstacles to porting is that the teams that originally built these features have mostly moved on. Luckily for ASP.NET customers, the ASP.NET team were the drivers behind .NET Core. MVC, Web API, and SignalR are all available in .NET Core or are on the roadmap.
Framework features not ported to Core
I provide this list with the knowledge that things can change. Some features don’t apply to non-Windows platforms, and other features won’t be carried forward by Microsoft into the future, either because there are better replacements or the feature was problematic in some way (insecure, hard to maintain, etc.).
- WPF/XAML – The Windows Presentation Foundation is only meant for user interfaces. The .NET Standard Library doesn’t include UI libraries and .NET Core doesn’t attempt to provide a cross-platform UI framework. This means things like Windows Forms and System. Drawing aren’t ported to .NET Core.
- Transactions – This library made it easy to create distributed transactions. It relies on Windows-specific components, making itnotreadily portable to .NET Core.
- AppDomains – These were useful for isolating assemblies tounload them without killing the process, which is great for applications that allow plugins. They rely on some Windows-specific constructs that wouldn’t work on other operating systems.
- .NET remoting – Remote objects have been succeeded by REST services.
- ASMX – An old way of writing web services that has been replaced by Web API.
- Linq to SQL – Replaced by Entity Framework.
- WCF services – Windows Communication Foundation client capabilities are available in .NET Core, but you can’t create services.
- WF – Windows Workflow Foundation depends on XAML, WCF services, and transactions among other .NET Framework-only features.
Subtle changes for .NET Framework developers
Experienced .NET Framework developers may encounter a few surprises working in .NET Core. Writing new code should be relatively straightforward because you’re unlikely to use older constructs like HashTable
or ArrayList
. Visual Studio’s Intellisense also indicates whether a type, method, property, etc. is supported in .NET Core.
Figure 5 Visual Studio IntelliSense indicates if a class or member is available in .NET Core
.NET Portability Analyzer
If you’re attempting to convert an existing .NET application to .NET Core, the best place to start would be the .NET Portability Analyzer. It’s available both as a command line application and a Visual Studio plugin. Many .NET platforms exist to choose from:
Figure 6 Target platforms available in .NET Portability Analyzer
This tool creates a detailed report with useful suggestions wherever possible:
Figure 7. .NET Portability Analyzer report
Reflection
Reflection works differently in .NET Core than in the .NET Framework. The most noticeable difference is that a lot of the operations normally available in the Type
class are no longer there. Some have been moved to a new class called TypeInfo
. Other operations aren’t available in the .NET Standard library and require an extra dependency.
Original code in .NET Framework.
PropertyInfo targetProperty = null; foreach (var property in owningElement.GetType().GetProperties()) { if (property.Name == this.Name && property.PropertyType.IsGenericType) {
The .NET Core port of the previous code.
PropertyInfo targetProperty = null; foreach (var property in owningElement.GetType().GetProperties()) ? { if (property.Name == this.Name && property.PropertyType .GetTypeInfo().IsGenericType) ? {
? Requires dependency on System.Reflection.TypeExtensions
? Many Type operations moved to TypeInfo
Summary
The software development industry is constantly evolving. Everything is challenged and improved, from languages to frameworks to tools to methodologies. The .NET Framework has reached a point where it’s too rigid and monolithic to keep up with competitors. .NET Core is a necessary next step in the evolution of .NET. It combines the best of the .NET Framework with the practices used in modern software development. Features like portability, simple deployment, high performance, open source, and great support make it worth checking out.
If you’re after more great .NET Core know-how, check out the book on liveBook here and see this slide deck.