ASP.NET Core 3: Add Entity Framework Core to Existing Project

Last week was an unofficial kicked off a series of posts associated with a refresh of the ASP.NET Basics repo frequently reference in this blog to reflect the state of affairs now that .NET Core 3 has been released. The new repo is ASP.NET Basics Refresh because naming is hard.

This post is going to take the API project created last week for the Swagger/OpenAPI with NSwag and ASP.NET Core 3 post and replace the generated data with a database using Entity Framework Core. If you want to follow along with this post the files before any changes can be found here.

Add NuGet Packages

Entity Framework Core is no longer included with .NET Core by default so we install a couple of NuGet packages to get started. I’m going to give the .NET CLI command, but this could also be done using the Visual Studio NuGet Package Manager UI. This post will also be using SQLite, but Entity Framework Core supports multiple databases you would need to install the package for the database you are interested in using.

Here are the commands to install the package we will be using. This is also assuming your terminal is in the same directory as the project file.

dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design

Add a DbContext

Just as a reminder we already have a Contact class in the Models directory with the following definition.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, I added a Data directory to the project and then added a new class called ContactedDbContext. The DbContext only exposes one DbSet for Contacts.

public class ContactsDbContext : DbContext
{
    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext(DbContextOptions<ContactsDbContext> options) 
        : base(options)
    { }
}

Configuration for the Connection String

In the appsettings.json file, which is where the application will pull configuration from by default, we are going to add a connection strings section to hold our default connection. The following is my full appsettings.json with the connection string for SQLite. If you are using a different database provider your connection string could be drastically different.

{
  "ConnectionStrings": {
    "DefaultConnection": "DataSource=app.db"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Check out Configuration in ASP.NET Core for more details on the different ways to handle configuration.

Register DbContext with the Services Container

Open Startup.cs and in the ConfigureServices function, we are going to use the AddDbContext extension method to add our new DbContext and tell it to use SQLite with the connection string from our appsettings.json. The following is the full function with the first two lines being the ones we added.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ContactsDbContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));

    services.AddControllers();
    services.AddOpenApiDocument(document => 
        document.PostProcess = d => d.Info.Title = "Contacts API");
}

Check out the official doc for more information on Dependency injection in ASP.NET Core.

Create and Apply Initial Migration

For this bit, we are going to head back to the command line open to the directory that contains the csproj for the project we are working with. The first thing we need to do is to install the Entity Framework Core Tool using the following command which will install the tool globally.

dotnet tool install --global dotnet-ef

Next, we will create a migration called Initial that output in the Data/Migrations directory using the following command.

dotnet ef migrations add Initial -o Data/Migrations

Now that we have a migration lets use it to create our database. Note that the same command will be used in the future when applying migrations to an existing database.

dotnet ef database update

Check out the official docs for more information on the Entity Framework Core Tool or Global Tools in general.

Scaffold a New Controller

If you are using the code from GitHub at this point you will need to delete the ContactsController as it is going to be recreated using Visual Studio’s tooling.

Right-click on the directory where the controller should be created, the Controllers directory in the example, and select Add and then Controller.

On the dialog that pops up, we want to select API Controller with actions, using Entity Framework and then click Add.

On the next screen specify the model classdata context, and controller name before clicking Add. In the sample case, we are going to use our Contact class for the model, ContactDbContext for the data context to generate a controller named ContactController.

After clicking add the requested controller will be generated with all the functions needed for CRUD operations for the selected model class. The code for our sample controller can be found here.

Try it out

Running the application and hitting our swagger UI with the help of NSwag we can see all the options our API has available and even try them out which will now hit our application’s database.

Another great option to test out APIs which has a lot of really great features is Postman. Either option will allow you to try out your API without having to build a client.

Wrapping Up

Hopefully, this post will help you get a jump start on integrating Entity Framework Core in your ASP.NET Core 3 applications. As a reminder Entity Framework Core supports a lot of different database providers. If you have any question I recommend checking Microsoft’s official docs on Getting Started with Entity Framework Core.

The code with all the above changes can be found here.

Swagger/OpenAPI with NSwag and ASP.NET Core 3

Now that .NET Core 3 is out I thought it would be a good time to revisit exposing API documentation using Swagger/OpenAPI. In the past, I have written posts on using Swashbuckle to expose Swagger documentation, but for this post, I’m going to try out NSwag.

What is OpenAPI vs Swagger?

To quote the Swagger docs:

OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs. An OpenAPI file allows you to describe your entire API. API specifications can be written in YAML or JSON. The format is easy to learn and readable to both humans and machines.

Swagger is a set of open-source tools built around the OpenAPI Specification that can help you design, build, document and consume REST APIs.

What is NSwag?

Quoting the NSwag GitHub readme:

NSwag is a Swagger/OpenAPI 2.0 and 3.0 toolchain for .NET, .NET Core, Web API, ASP.NET Core, TypeScript (jQuery, AngularJS, Angular 2+, Aurelia, KnockoutJS and more) and other platforms, written in C#. The OpenAPI/Swagger specification uses JSON and JSON Schema to describe a RESTful web API. The NSwag project provides tools to generate OpenAPI specifications from existing ASP.NET Web API controllers and client code from these OpenAPI specifications.

One neat thing about NSwag is it also has the tooling to help generate the API consumer side in addition to the OpenAPI specs.

Sample Project

For this post, I created a new API project via the .NET CLI using the following command. Not that all this can be done via the Visual Studio UI if that is your preference.

dotnet new webapi

For me, this project is going to be the start of a new series of posts so I also added a solution file and added the project created above to it. These commands are optional.

dotnet add sln
dotnet sln add src\ContactsApi\ContactsApi.csproj

Add NSwag

Using the CLI in the same directory as the project file use the following command to add a reference to NSwag.AspNetCore to the project.

dotnet add package NSwag.AspNetCore

Next, in your favorite editor open the project/directory we created and open the Startup.cs file. In the ConfigureServices function add services.AddOpenApiDoccument.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddOpenApiDocument();
}

Then at the end of the Configure function add calls to app.UseOpenApi and app.UseSwaggerUi3.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    app.UseOpenApi();
    app.UseSwaggerUi3();
}

Note that NSwag also supports ReDoc if you prefer that over Swagger UI.

Sample Model and Controller

Now that we have NSwag installed let’s create a new endpoint for it to display. As per my norm, I will be doing this using contacts as an example. First I created a Models directory and then added the following Contact class to it.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, in the Controllers directory add a ContactsController, which in the following code returns a list of 5 generic contacts.

[ApiController]
[Route("[controller]")]
public class ContactsController : ControllerBase
{
    private readonly ILogger<ContactsController> _logger;

    public ContactsController(ILogger<ContactsController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<Contact> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new Contact
        {
            Id = index,
            Name = $"Test{index}",
            Address = $"{index} Main St.",
            City = "Nashville",
            State = "TN",
            PostalCode = "37219",
            Phone = "615-555-5555",
            Email = $"test{index}@test.com"
        });
    }
}

Results

Run your project and then in a browser navigate to your base URL /swagger. For example my for my project that is https://localhost:5001/swagger. You should see something like the following that will let you explore your API and even execute requests against your API using the Try it out button you see in the UI.

Wrapping Up

Just like with Swashbuckle, NSwag makes it very easy to get started providing API documentation. This post just covers the very basics and I’m looking forward to digging into some of the more advanced features that NSwag has such as client generation.

Microsoft has a great article on Getting Started with NSwag on their docs site that I recommend reading. This is a preview of something I plan to cover in the future, but there are attributes that can be added to controllers that help NSwag provide better details about what your API can return and Microsoft has a doc on Use web API conventions that makes it easy to apply some of the common conventions.

Migration from ASP.NET Core 2.2 to 3.0

On September 23rd .NET Core 3.0 was released including ASP.NET Core 3.0 and Entity Framework Core 3.0. This post will be taking the Contacts project used in the ASP.NET Basics series and migrating it from .NET Core 2.2 to .NET Core 3.0. Most of the information used for this migration comes from the Microsoft docs which will cover way more scenarios than this post will.

The code before any changes can be found in this GitHub repo. A reminder that the Contacts project is the only project being updated with this post the projects in the repo will remain on ASP.NET Core 2.2 for now.

Installation

If you are a Visual Studio user you can get .NET Core 3.0 by installing at least Visual Studio 16.3. For those not using Visual Studio, you can download and install .NET Core 3.0 SDK from here. As with previous versions, the SDK is available for Windows, Linux, and Mac.

After installation is complete you can runt the following command from a command prompt to see all the versions of the .NET Core SDK you have installed.

dotnet --list-sdks

You should see 3.0.100 listed. If you are like me you might also see a few preview versions of the SDK that can be uninstalled at this point.

Project File Changes

Right-click on the project and select Edit projectName.csproj.

Change the TargetFramework to netcoreapp3.0.

Before: 
<TargetFramework>netcoreapp2.2</TargetFramework> 

After: 
<TargetFramework>netcoreapp3.0</TargetFramework>

The packages section has a lot of changes. Microsoft.AspNetCore.App is now gone and part of .NET Core without needing a specific reference. The other thing to note is that Entity Framework Core is no longer “in the box” so you will see a lot of references add to make Entity Framework Core usable.

Before:
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />

After:
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" PrivateAssets="All" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />

The last thing to note is that Swashbuckle doesn’t have a final version ready for .NET Core 3 so you will have to make sure you are using version 5 rc2 at a minimum.

The following is my full project file for reference.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    <UserSecretsId>aspnet-Contacts-cd2c7b27-e79c-43c7-b3ef-1ecb04374b70</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" PrivateAssets="All" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />
  </ItemGroup>

</Project>

Program Changes

In Program.cs some changes to the way the host is constructed. The over version may or may not have worked, but I created a new app and pulled this out of it just to make sure I’m using the current set up.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace Contacts
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                                          {
                                              webBuilder.UseStartup<Startup>();
                                          });
    }
}

Startup Changes

In Startup.cs we have quite a few changes to make. As long as you haven’t do any customization in the constructor you can replace it with the following.

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

Next, they type on the configuration property changed from IConfigurationRoot to IConfiguration.

Before:
public IConfigurationRoot Configuration { get; }

After:
public IConfiguration Configuration { get; }

Moving on to the ConfigureServices function has a couple of changes to make. The first is a result of updating to the newer version of the Swagger package where the Info class has been replaced with OpenApiInfo.

Before:
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info { Title = "Contacts API", Version = "v1"});
});

After:
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1",  new OpenApiInfo { Title = "Contacts API", Version = "v1" })
});

Next, we are going to move from using UserMvc to the new AddControllersWithViews which is one of the new more targeted ways to add just the bits of the framework you need.

Before:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

After:
services.AddControllersWithViews();

Now in the Configure function, the function signature needs to be updated and the logging factory bits removed. If you do need to configure logging that should be handled as part of the HostBuilder.

Before:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

After:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{

For the next set of changes, I’m just going to show the result and not the before. The UseCors may or may not apply but the addition of UserRouting and the replacement of UseMvc with UserEndpoint will if you want to use the new endpoint routing features.

app.UseStaticFiles();
app.UseRouting();

app.UseCors(builder =>
            {
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
                builder.AllowAnyOrigin();
            }
           );

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
                 {
                     endpoints.MapControllerRoute(
                                                  name: "default",
                                                  pattern: "{controller=Home}/{action=Index}/{id?}");
                     endpoints.MapRazorPages();
                 });

Other Miscellaneous Changes

The only other change I had was the removal of @using Microsoft.AspNetCore.Http.Authentication in a few cshtml files related to login.

Wrapping Up

The migration from 2.2 to 3.0 is a bit more involved than the move from 2.1 to 2.2, but that isn’t surprising with all the changes in this release. Remember to check out the official migration guide for more details.

The code for the Contacts project after the above changes can be found on GitHub.

Migration from ASP.NET Core 2.1 to 2.2

On December 4th .NET Core 2.2 including ASP.NET Core 2.2 and Entity Framework 2.2. In this post, I will be taking one of the projects used in the ASP.NET Basics series and converting it from ASP.NET 2.1.x to the new 2.2 version of ASP.NET Core. This will all be based on the official 2.2 migration guide.

The code before any changes can be found here. In the sample solution, this guide will be working with the Contacts project only.

Installation

Head over to the .NET download page and download the new version of the .NET Core SDK for version 2.2 which is available for Window, Linux and Mac.

After installation is done run the following command if you want to verify the SDK is installed.

dotnet --list-sdks

You should see 2.2.100 listed. If you are like me you might also see a few preview versions that would be good to uninstall.

If you are using Visual Studio make sure you are on at least version 15.9. If not updates can be downloaded from here.

Project File Changes

Right-click on the project and select Edit projectName.csproj.

Change the TargetFramework to netcoreapp2.2.

Before:
<TargetFramework>netcoreapp2.1</TargetFramework>
After:
<TargetFramework>netcoreapp2.2</TargetFramework>

Update any Microsoft packages with a version to 2.2.x the following is an example.

Before:
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" PrivateAssets="All" />

After:
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" PrivateAssets="All" />

If you want to use the new IIS in-process hosting model you also need to add the following line to a property group.

<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>

The following is my full csproj for reference.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    <UserSecretsId>aspnet-Contacts-cd2c7b27-e79c-43c7-b3ef-1ecb04374b70</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
  </ItemGroup>

</Project>

Startup Changes

In Startup.cs update the compatibility version to enable the new 2.2 features.

Before:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

After:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Wrapping Up

As with the migration to 2.1 the move to 2.2 is really easy to do. Make sure you check out the official migration guide for more details that may have not been covered by this project.

The code in its final state can be found here.

ASP.NET Core 2.1: ActionResult

This post is going to take the Contacts API from my ASP.NET Basics set of posts and move it from using IActionResultto ActionResult<T> which was introduced with the 2.1 release. The changes are really simple, but if you are using OpenAPI/Swagger I have a call out later in the post about something I noticed. The code before any changes can be found here.

IActionResult vs ActionResult<T>

The official docs explain the three different ways to return data in an API which are a specific type, IActionResult type, or ActionResult<T> type.

A specific type is great if you don’t have to do any sort of validation or the like, but as soon as you need to return a different HTTP status than OK is no longer sufficient. This is where you would have to move to IActionResult.

IActionResult allows different HTTP statuses to be returned. In the following example, NotFound is returned if a contact with the supplied ID isn’t found or OK(contact) if a contact is found.

public async Task<IActionResult> GetContact([FromRoute] int id)
{
     var contact = await _context.Contact
                                 .SingleOrDefaultAsync(m => m.Id == id);

     if (contact == null)
     {
        return NotFound();
     }
    
     return Ok(contact);
}

The advantage of ActionResult<T> it is the return type of the function is clear. You can see in the following example where GetContact has been changed to use ActionResult<T> that if all goes well you will be dealing with a Contact object in the end without the need to wrap the result in an OK.

public async Task<ActionResult<Contact>> GetContact([FromRoute] int id)
{
     var contact = await _context.Contact
                             .SingleOrDefaultAsync(m => m.Id == id);

     if (contact == null)
     {
        return NotFound();
    }

    return contact;
}

OpenAPI/Swagger

If you are using OpenAPI/Swagger in your project with a function with the following definition it will automatically pick up the return type if you switch to using ActionResult<T>.

public async Task<ActionResult<Contact>> GetContact([FromRoute] int id)

The above function results in the following in OpenAPI/Swagger UI.

This is awesome and saves you from having to ProducesResponseType attributes to your API functions. Just note that as soon as you do add a ProducesResponseType for say a NotFound response you will still need include a response for OK with the proper type or you will lose the return type in the OpenAPI/Swagger UI.

I’m calling that last bit out because I spent time trying to figure out why all the samples I saw the return type was automatically picked up, but in my sample application it wasn’t.

Wrapping Up

I’m a huge fan of ActionResult<T> mostly because of the clarity it adds to API function definitions. The fact that OpenAPI/Swagger can pick up on it in the simple cases is an added bonus.

If you are looking for more info check out the Exploring ActionResult<T> in ASP.NET Core 2.1 post by Joonas Westlin in which there is more info on how the functionality is actually implemented. If you didn’t already make sure and check out the Controller action return types in ASP.NET Core Web API page in the official docs for a detailed comparison of the return type options for APIs.

The completed code can be found here.

ASP.NET Core Basics: Blazor

Blazor is a single page application framework that uses .NET running in the browser through the magic of WebAssembly and Mono. Check out How Blazor runs .NET in the browser for more information. You can think of Blazor like you do Angular or React, but written in .NET.

Please make note that this project is still an unsupported experiment and shouldn’t be used for production applications. This is part of the reason I held off on trying it until now.

I will be adding the Blazor project to my ASP.NET Core Basics repo. The code before any changes can be found here.

Getting Started

For an experiment, Blazor already has some really good docs. A lot of this post is going to mirror the Get started with Blazor docs page, but I try and document as I go. First, make sure you have the latest version of .NET Core 2.1.x SDK installed.

If you are going to be using Visual Studio you will need at least version 15.7. In addition, you will need to install the Blazor Language Services extension. From within Visual Studio, this can be done from the Tools > Extension and Updates menu. Select Online and search for Blazor. It should come up with just one item and you can click Download to start the install process.

Project Creation

We are going to use the .NET CLI to install the Blazor templates and add the resulting project to the ASP.NET Core Basics solution. First, open a command prompt and use the following command to get the Blazor template installed.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates

If you are using the sample code I am running the commands from a new Blazor directory in the existing src directory. Then run the following command to create the Blazor project.

dotnet new blazor

The next command will add the new project to the existing solution. The path to the solution file isn’t required if the command is being run from the same directory as the solution file, but in our case, we are running the commands two level down from where the solution file is located.

dotnet sln "../../ASP.NET Core Basics.sln" add Blazor.csproj

At this point, you can use the following command to run the application.

dotnet run

Adding the Contact List

As with the other post in the ASP.NET Basics category, we are going to add a contact list page that pulls a list of contacts from an API. For this example, the API is part of the Contacts project that already exists in the sample solution. All the changes in the section take place in the Blazor project we created above.

In the Pages directory add a ContactList.cshtml file with the following contents. A break down of some of the parts of this file will follow.

@page "/contacts"
@inject HttpClient Http

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
}

This has a lot going on so we are going to start with the functions section which is essentially a way to block off code needed by the page. It can contain functions, classes, or whatever else C# construct the page may need. The following is just the functions section of the above page.

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
}

In our sample, we are using the functions to define a Contact class to hold the data we get back from the API call in the OnInitAsync function. The OnInitAsync function is one of the lifecycle functions provided by the Blazor components. We aren’t going to dive into components, I recommend you check out the component docs for more information.

The @page "/contacts" is defining the route that the page will be served for. Next, @inject HttpClient Http is showing how to use ASP.NET Core’s dependency injection to get an instance of an HttpClient.

The remaining bit of the file is normal Razor. Everything defined in the functions section is available for use in your layout. For example, we are using the list of contacts filled by the OnInitAsync to loop and create a table to display our contact list.

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

Wrapping Up

Blazor is a very interesting concept. I hope it is able to make it through the experimental phase into a supported project. It seems like it would be a great option for .NET developers. It was a lot of fun to finally try out. Go give it a try and make sure and provide feedback to Microsoft so they can make an informed decision on how to proceed with the project.

The finished code can be found here.

Migration from ASP.NET Core 2.0 to 2.1

On May 30th .NET Core 2.1 was released including the corresponding version of ASP.NET Core 2.1 and Entity Framework Core 2.1. In this post, I will be taking one of the projects used in my ASP.NET Basics series and converting it from its current 2.0.x version into the newly released 2.1 version. The starting point for the code can be found here. This is all based on the official migration guide.

If you are looking at the sample solution it is the Contacts project that this post is going to be dealing with.

Installation

Thankfully the download page is much improved over the last time there was a release. Head here and to download and install the .NET Core 2.1 SDK. It is available for Windows, Linux, and Mac. The link should drop you on the appropriate page for your OS.

After installation, open a command prompt and run the following command. If all worked well you should see version 2.1.300 listed.

dotnet --list-sdks

If you are on Windows make sure and install at least Visual Studio 2017 15.7.

Project File Changes

Right-click on the project and select Edit {projectName}.csproj from the menu.

First, change the TargetFramework to netcoreappp2.1.

Before:
<TargetFramework>netcoreapp2.0</TargetFramework>

After:
<TargetFramework>netcoreapp2.1</TargetFramework>

The other required changes it to move away from the Microsoft.AspNetCore.All package to the version-less Microsoft.AspNetCore.App package.

Before:
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />

After:
<PackageReference Include="Microsoft.AspNetCore.App" />

I did a bit more digging and it turns out that the project file can be greatly simplified from the version I had for this application. The following is the full project file will all the bits that were not required removed and the two changes above already made.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <UserSecretsId>Your-Secrests-ID</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0" PrivateAssets="All" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
  </ItemGroup>

</Project>

Main Changes

There have been changes to how what the Main function looks like to better allow for integration tests. This is the original code in the Program.cs file.

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

And the following is the new version.

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Startup Changes

Startup.cs has one change that is required which is the removal of the following line from the Configure function.

app.UseBrowserLink();

In the ConfigureServices function if you want to use the new features in 2.1 change the services.AddMvc() to set the compatibility version. This allows you to upgrade the version of the SDK without having to change your whole application since you have to opt into the version you want to target.

Before:
services.AddMvc();

After:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

If you check out the official migration guide they also point out how to enable a couple more features such as HTTPS and some things to help with GDPR. Neither of these is needed in this application so I’m skipping them in this guide.

Identity Changes

I had to make one change in ManageLogins.cshtml to get my project to build because of a rename/removal AuthenticationScheme to DisplayName.

Before:
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>

After:
<button type="submit" class="btn btn-default" name="provider" value="@provider.DisplayName" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>

If you haven’t made many changes to the identity code in your project you might consider using the new identity razor class library. You can find the details here.

Wrapping Up

Migrations between versions of ASP.NET Core have gotten easier over time as you can tell by the smaller length of these posts. One thing to note is while this will get you targeting 2.1 with all the performance benefits and access to a lot of the new features there will still be work needed if you want to do everything the new 2.1 style. I highly recommend creating a new 2.1 application to get a feel for the other changes you might want to make to your existing applications.

The code with all the changes can be found here. Remember that the only project that was upgraded was the Contacts project.

Trying the New ASP.NET Core Angular Template with CLI Support

I got hit by the flu that has been going around and now that the fever has passed I thought it would be a good time to try out the new version of the Angular template for ASP.NET Core that works well with the Angular CLI.

Template Installation

Note that at the time of this writing the templates are in the release candidate stage and a new version could be available by the time you are reading this so make sure and check this page for potential updates.

Running the following command from a command prompt will install the RC version of the templates.

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.0.0-rc1-final

Project Creation

Create a directory for the project and navigate to it in a command prompt. Run the following command to create the new Angular project.

dotnet new angular

Next, if you have a solution you want to add the new project to that can be done with the following command adjusting for the naming of your project and solution.

dotnet sln "ASP.NET Core Basics.sln" add src\AngularWithCli\AngularWithCli.csproj

Installation of Angular CLI

From the command prompt run the following command to install the Angular CLI globally.

npm install -g @angular/cli

After the above, I got the following error trying to run any Angular CLI commands.

You seem to not be depending on “@angular/core”. This is an error.

The problem ended up being that I had not installed all the packages for the project. The issue was cleared up by the following command.

npm install

Angular CLI Usage

Navigate to the ClientApp directory and you can then use all the Angular CLI commands as you would in a stand along Angular application. Some of which can be found here. If you are looking for a quick command to verify all is work the following command works well by running a linter on your project.

ng lint

Wrapping Up

Having templates that are compatible with the Angular and React CLI is a big step forward. The CLIs provide a lot of functionality and by having a setup that doesn’t restrict their usages is a great move. Make note that server-side rendering is no longer enabled by default, but can still be enabled for Angular projects, but not React based projects.

I recommend you check out the official documentation which can be found here.

I hope we see these functionality moves to the other templates that are outside of the templates in this package in order to support Aurelia and Vue.

ASP.NET Core Basics: Razor Pages

As part of the ASP.NET Core 2.0 release, a new feature called Razor Pages was added to better handle page-focused scenarios. This post is going to cover adding usage of Razor Pages to an existing ASP.NET Core MVC application. This is part of the ASP.NET Core Basics series and the repo before any changes for this post can be found here. All the changes will be in the Contacts project if you are using the sample repo.

Add the end of this post the Razor Pages example will have the same level of functionality as the existing Razor example in the project.

Setup

To follow the conventions of a new Razor Pages project add a Pages directory to the root of the project. As another level of grouping add a ContactsRazorPages directory under the Pages directory. The strange name of the directory is just to make it super clear this is different than the existing Contact List already in the application.

Scaffolding

Razor Pages supports the same level of scaffolding as the existing Razor/MVC setup we are all used to in Visual Studio. To start, right-click on the ContactsRazorPages directory and select Add > Razor Page.

This will open the Add Scaffold dialog. We are using entity framework and want to generate a full set of CRUD operations so select Razor Pages using Entity Framework (CRUD) and click Add.

Next, we have to select the Model and DB Context. We want to use the same model and context as our existing Razor/MVC setup so we are going to select the Contact class and the ContactsContext DB Context. Finally, since this is part of an existing application make sure and check the Use a layout page and use the existing _Layout.cshtml page used by the rest of the application. Click the Add button and hang out while the magic happens.

After a couple of minutes, the directory will be filled with a set of pages to do contact CRUD operations. Since this is a page-centric method of working all the files you need are in this one directory. No separate controller and views as in traditional MVC. By default, routing is handled via the folder structure.

View Imports

I had to a _ViewImports.cshtml file to the Pages to get things working. I tried adding the needed imports to the existing import, but it didn’t work for some reason. Here are the contents of the file.

@using RazorPages
@namespace RazorPages.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Add to the Navigation Menu

Our last step is going to be to add the new contact list to the site’s navigation menu. Open the _Layout.cshtml file in the Views/Shared directory and a link to the new contact list.

Existing MVC based contact list:
<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contact List</a></li>

New Razor Pages based contact list:
<li><a asp-page="/ContactsRazorPages/Index">Contact List (Razor Pages)</a></li>

Notice that the link uses the asp-page tag helper instead of asp-controller.

Wrapping Up

The above covers adding Razor Pages to an existing MVC application and rounds out the all the major UI options for the ASP.NET Basics series. Keep in mind that Razor Pages functionality is fully on par with tradition MVC and has been recommended by Microsoft as the way to do when page-centric work. If you haven’t check out the getting started docs to get a better feel for how to use pages.

The completed code can be found here.

Identity Server: Upgrade Client to Angular 5

I have been working a lot on my basics sample project to explore some new client-side frameworks (React and Vue if you are interested). Since I have been away from the Identity Server sample for a while I thought it would be good to see what updates the project might need. It turns out that Angular was the big thing that was out of date. This post is going to cover the changes to get the project updated to Angular 5.

Package.json

In the Client App project open the package.json file and update the version of the @angular packages to at least the following version, and of course feel free to pin the exact version. I don’t just because of the nature of this sample.

"@angular/animations": "^5.0.0",
"@angular/common": "^5.0.0",
"@angular/compiler": "^5.0.0",
"@angular/compiler-cli": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
"@angular/http": "^5.0.0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/platform-server": "^5.0.0",
"@angular/router": "^5.0.0"

At this point, I tried to run and got an error about the version of rxjs being used. Instead of just blindly going package by package and seeing which versions were required I installed the Angular CLI and created a new Angular 5 application and used it as an example of what version I needed. Use the following commands if you would like to follow the same process since the current versions have changed by the time you are reading this post.

npm install -g @angular/cli
ng new sample-app

The above led me to the following version changes.

"rxjs": "^5.5.2",
"zone.js": "^0.8.14"

Attempt 2

At this point, I tried running the application again and received the following error.

Error: Version of @angular/compiler-cli needs to be 2.3.1 or greater. Current version is “5.0.1”.

As you can imagine I was surprised that 5.0.1 < 2.3.1. Turns out this is related to the version of @ngtools/webpack. This package deals with ahead-of-time compiling which my sample application uses, but the application I generated using the Angular CLI doesn’t. Updating to the following version cleared up the issue.

"@ngtools/webpack": "^1.8.0"

Open ID Connect Client

There was a much new version of the Open ID Connect Client that the Angular application is using so I upgrade it as well to the following version.

"angular-auth-oidc-client": "3.0.4"

This version dropped the startup_route so the following line had to be removed from the AuthService class.

openIdImplicitFlowConfiguration.startup_route = '/home';

Final Steps

Now that the package versions are sorted run the following commands from a command prompt to make sure that all the new version are installed and in the proper places.

npm install
node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js
node node_modules/webpack/bin/webpack.js

Wrapping Up

I am glad to have this upgrade done. It seems that every time I do one of these upgrades I end up down some rabbit hole. On the plus side, I seem to be getting faster at resolving the rabbit hole issues, or the frameworks have made a lot of progress on making sure the upgrade processes are simpler than they used to be. Either way, I get to expand my knowledge. I just need to schedule a bit more time before attempting upgrades.

The code in its finished state can be found here.