Asp.Net Core Overview

Spending the past year on building and supporting Unison.School gave me an in-depth, full-stack experience in developing web apps with Asp.Net Core. In this post, I will describe the basic components and aspects of Asp.Net Core, and give my personal opinions on the software.

PowerPoint Presentation

Development

Runtime

Asp.Net Core is an implementation of .NET Core, which runs on the CoreCLR runtime, which is a virtual machine that executes .NET code. Unlike the .NET Framework, which is Windows-specific, .NET Core is designed to be able to run on multiple platforms, including Windows, MacOS, and Linux.

Asp.Net Core is designed to make Web Apps and Wep APIs which are deployable on any system above, as well as in Azure Web Apps or Docker containers. It is built on the decades of experience with Asp.Net and Asp. In addition to adding cross-platform capabilities, Asp.Net Core introduces built-in Dependency Injection and support for Razor Pages. Like Asp.Net, you still have access to traditional routing and model binding features.

.NET Standard

One goal that Microsoft has pushed toward while releasing .NET Core, is to also increase the re-usability of .NET code across multiple projects. With .NET Standard, they have succeeded. .NET Standard is a compatibility requirement or specification that the most recent versions of .NET Core, .NET Framework, Mono, and Xamarin all meet.

This specification means that you can write .NET Standard libraries, and access them from any modern .NET project. When creating an Asp.Net Core web app, it gives you the ability to share large amounts of code with future mobile or desktop apps.

Visual Studio

Any experienced .NET developer is familiar with Visual Studio. VS 2017 supports Asp.Net Core, and includes multiple starter templates to help you build a web app or API.

Visual Studio Template Options

VS also supports graphical interfaces for Nuget, git, and other extensions.

Command Line

For those interested in a quick clean start, or using a different editor than Visual Studio, there are also simple .NET Core commands, such as dotnet new, dotnet build, and dotnet run.

Dependency Injection

DI Setup in Startup.cs

I love the magic of Asp.Net Core’s Dependency Injection (DI). While there are many third-party DI frameworks that probably work just as well, it is nice to offer this as a built-in feature, to encourage good code architecture. I have worked on projects without DI, and while it works, the factories to instantiate objects can be verbose and confusing at times.

Templates and Applications

As stated above, the two main uses for Asp.Net Core are for Web Apps and Web APIs.

Web APIs

The API template gives you a very simple project with Controllers that listen for web calls and route them to specific actions.

Controller

This simple interface can then be connected to any business classes, databases, or other services.

MVC Web Apps

The MVC (Model, View, Controller) web app template builds upon the Controller foundation from the API template, and adds Models (aka Data-Transfer Objects, View Models), and Razor Views, which are HTML pages with embedded C# code, that is converted into HTML on render. Each Controller can return one or more views as an Action Result.

View Model (Data Transfer Object)
Razor View

The nice thing about the MVC approach is the very clear separation of concerns between the Controllers and the Views. However, this can also be potentially more structure than is needed, especially for web sites that do not also include API services.

Razor Pages

A more recent model for Asp.Net Core is that of Razor Pages. While Razor Pages use the same cshtml structure as Razor Views, they also each come with a PageModel c# file, which is more akin to MVVM designs or XAML code-behind classes.

PageModel
Razor Page

Notice that the only difference in the Razor file between a View and a Page is the tag @page at the top.

The Razor Page PageModel is great for organizing all the relevant code for a specific page in one place. However, unlike a Controller class, it is not ideal for handling multiple various calls, such as AJAX and API requests.

 

Front-End Frameworks

Asp.Net Core is completely compatible with any front-end (client-side) web frameworks. As you can see in the templates image above, starter templates exist for using Asp.Net Core with both Angular and React. Templates for other frameworks can be found online.

Blazor

Blazor is an exciting new development for the .NET community. Based on the new WebAssembly (WASM) standard, frameworks can now be written to compile code in any language to be run in the browser! The Mono development team has taken on this challenge, creating a .NET runtime that runs in WASM and on the browser.

Blazor is designed to take the existing Razor syntax, and use it via Mono/Wasm to replace other front-end javascript frameworks. While exciting, this project is still in it’s infancy, and not ready for production apps.

 

Extensions

As .NET Standard compliant, Asp.Net Core opens us up to a huge variety of Nuget packages that are compatible with our web apps.

Entity Framework Core

Entity Framework is a .NET Object-Relational Mapping (ORM) framework that wraps SQL Server or other databases in a level of abstraction, allowing C# writers to model, query, and save to the database without leaving the familiar .NET language. EF Core is re-written specifically to work with the .NET Core framework, and it can be included in new projects with a click of a button, or imported from Nuget.

EF Core Database Context

Signal-R

While I haven’t had a chance to explore this yet, the real-time web communication library Signal-R has recently been given an Asp.Net Core library.

 

Deployment

Asp.Net Core apps can be deployed on any Windows Server via IIS, just like traditional Asp.Net. However, as a cross-platform solution, they may also be deployed on a Linux server via Apache or Nginx. On Azure, you can use an App Service instance to upload your app as a managed service, without the need to deal with the server at all!

Azure App Service Portal

Azure also gives you tons of tools for managing your app, including Application Insights, auto-scaling, and site and database backups.

ToCode.Software

Many self-taught programmers, myself included, become easily overwhelmed by modern app and web development tutorials. My thought is that this is caused by the combination of UI, Database, and logic layers. So I decided to make ToCode.Software as a new type of tutorial.

I am a .Net developer, and I also love cross-platform code. There is a wonderful web tool, DotNetFiddle, that can help anyone from beginner to professional try out some simple C# code. I used DotNetFiddle as an embedded, interactive template for the beginning lessons of ToCode.Software, so users can try out code without ever leaving the site.

As the second step, I introduce Visual Studio Code, .Net Core, and the bash shell, so learners can start making their own simple console apps with file-based, object-oriented classes.

After going over many of the basics of the C# language and coding logic, there are two projects, a simple ChatBot, and a more complicated Go Fish Game. I hope to expand this series to include many of the following concepts:

  1. Adding an app UI with Xamarin.Forms
  2. Adding a web UI with HTML and CSS
  3. Connecting to a SQL database to store and retrieve data

I’d love some feedback on this project. Feel free to comment here, or on the site, and share!

Extricating AspNetCore Identity from Entity Framework Database for Xamarin

Unison.School has become a very large project. I’m proud of the hundreds of teachers who are using it in their schools, and hope to keep building it even larger.

I built Unison.School while learning the cutting-edge Asp.Net Core 2.0 framework, including the EntityFrameworkCore database ORM. Based on the starting templates for a web app, I built my Teacher and Student user models inheriting from the IdentityUser class. This provides lots of wonderful built-in functionality around logging in and authorizing access to specific pages.

In the year since laying out those login procedures, the model for the project has grown to over 100 entities in the database. A teacher, for example, could be connected to all the following entities:

Each of these, in turn, would be tied to even more tables. This was all fine and good until I looked to create a mobile app version of the service.

As you may know, Xamarin allows .Net programmers to share code with and across mobile platforms. What you may not have realized, if you are new to .Net and follow a path similar to mine, is that IdentityUser is not compatible with Xamarin. Yet I wanted to use many of these same classes in my mobile app, and it seemed ridiculous to create two copies of each entity, and have to maintain the code between them.

The model library included a link to the Nuget package for Microsoft.AspNetCore. EntityFrameworkCore.Identity, so I needed to move any code I wanted to reuse into a new portable class library, and reference it from both the Asp.Net Core app and the Xamarin app.

My first attempt to disentangle the model was to create an IApplicationUser interface, which both my Asp.Net Core ApplicationUser (base class for Teacher and Student) and a new mobile version could inherit from. I copied all the code that I cared about into this interface.


        public interface IApplicationUser
        {
            string Id { get; set; }
            string FirstName { get; set; }
            string LastName { get; set; }
            string UserName { get; set; }
        }
    

Next, I realized that I also needed to create new classes for Teacher and Student that did not inherit from IdentityUser. So I similarly created ITeacher and IStudent.

So far, so good. But now, let’s take the teacher’s LessonPlan object as an example. In the Teacher class we have:


        public List LessonPlans { get; set; }
    

And in the LessonPlan class:


        public string TeacherId { get; set; }
        public virtual Teacher Teacher { get; set; }
    

In the DbContext builder, the two are connected:


        builder.Entity()
            .HasOne(lp => lp.Teacher)
            .WithMany(t => t.LessonPlans)
            .HasForeignKey(lp => lp.TeacherId);
    

If I moved LessonPlan into the shared library, it could not reference Teacher. The same was true for all the other entities that had relationships with my user classes.

I initially thought I should perservere with a strategy I’ll call “Interface All the Things!” I created an ILessonPlan, and dozens of other interfaces. Each entity then referenced the interfaces, instead of the base classes. However, I discovered when moving back to the DbContext that this approach would not work. Entity Framework relationships must be between concrete classes, not interfaces. It is possible to cast a single object to it’s instantiation:


        builder.Entity()
            .HasOne(b => (Teacher)b.Teacher)
            .WithMany(t => t.LessonPlans)
            .HasForeignKey(b => b.TeacherId);
        // Casts ITeacher to Teacher
    

But this is not possible to do with a List<object>, which describes one side of all my one-to-many relationships.

I was definitely stumped for a long time, and could find no help on the internet for this scenario. Finally, while listening to my favorite podcast, Coding Blocks, they mentioned in one episode removing unneeded relationships, especially dual-directional ones! Since EF and all the tutorials show how to make the connections, it never occured to me not to connect two objects that I didn’t need to follow with a query!

Once I understood this, implementing was simple (although time-consuming). In the LessonPlan example, I removed the property public Teacher Teacher { get; set; }, but left the public int TeacherId { get; set; }. I was also able to delete the connection in the DbContext builder. This allowed me to move my LessonPlan and most other entities into the shared library, since there was no direct connection to the user classes.

A large portion of the time was then spent tracking down everywhere I had used a call such as lessonPlan.Teacher. While these were less common than calling teacher.LessonPlans, the need did arise. So now, in such instances, I did have to add one step:


        var teacher = DbContext.Teachers.Single(t => t.Id == lessonPlan.Id);
    

This extra line of code was a small price to pay to reuse my 100 classes in a new project! In the Xamarin project, you can also create a nearly identical DbContext, inheriting from the DbContext base class instead of from IdentityDbContext. I’d also like to point out how useful ReSharper is for a refactoring of this magnitude. It will automate a lot of namespace changes, search for usings, etc. I can’t imagine how long it would have taken me without that tool.