ASP.NET Core

Identity Server: Sample Exploration and Initial Project Setup

This post will be a continuation of my exploration around Identity Server which was started with this post which was more of an overview of the space and my motivations for learning about Identity Server. There were a lot of things that were unclear to me as I first started looking through the samples so this post is going to communicate so of those issues and hopefully clear them up for you as well.

After this post, the follow-up post should be more focused on one thing instead of trying to cover so much information in on go.

The following are all the posts in this series.

Identity Server: Introduction
Identity Server: Sample Exploration and Initial Project Setup (this post)
Identity Server: Interactive Login using MVC
Identity Server: From Implicit to Hybrid Flow
Identity Server: Using ASP.NET Core Identity
Identity Server: Using Entity Framework Core for Configuration Data
Identity Server: Usage from Angular

Typical Sample Solution Structure

I started my exploration with the IdentityServer4.Sample repo specifically in the Quickstarts folder. For me, this was a mistake as I didn’t have a good enough grasp on the larger concepts for the code to provide proper guidance. Big surprise here, but using the docs and actually walking through the project creation was very helpful.

The code associated with this blog can be found here. The solution contains three projects.

  • ApiApp – Backend for the application and is a resource that is will require authorization to access. The API will be an ASP.NET Core Web API.
  • ClientApp – Frontend application that will be requesting authorization. This is an ASP.NET Core application that is hosting an Angular (4) app.
  • IdentityApp – This is ASP.NET Core application that is the IdentityServer and will end up authorizing users and issuing tokens for resources.

Identity Application

For the Identity application, create an ASP.NET Core Web Application using the empty template targeting at least ASP.NET Core 1.1. Next, using NuGet install the IdentityServer4 NuGet package.

Now that the IdentityServer4 NuGet package is installed open up the Startup class and add the following to the ConfigureServices function.

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
        .AddTemporarySigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients());
}

The above registers IdentityServer with ASP.NET Core as a service available via dependency injection using temporary and in-memory components as a stand in for testing. The Config class used here will be added a bit later.

Next, the Configure function should look like the following.

public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env, 
                      ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDeveloperExceptionPage();
    app.UseIdentityServer();
}

The above is a basic Configure function. app.UseIdentityServer() is the only the only bit related to IdntityServer and it is adding it to the application’s pipeline.

The final part of this application is the Config class which is used to define the in memory test resources for this application. As you can see below it is defining both API resources and Clients. In the future theses, items would be pulled from a datastore.

public class Config
{
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("apiApp", "API Application")
        };
    }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "clientApp",

                // no interactive user, use the clientid/secret for authentication
                AllowedGrantTypes = GrantTypes.ClientCredentials,

                // secret for authentication
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },

                // scopes that client has access to
                AllowedScopes = { "apiApp" }
            }
        };
    }
}

API Application

For the API application, create an ASP.NET Core Web Application using the Web API template targeting at least ASP.NET Core 1.1. Next, using NuGet install the IdentityServer4.AccessTokenValidation NuGet package.

Ater the above NuGet package installed open up the Startup class. In the Configure function, the IdentityServer middleware needs to be added to the application pipeline before MVC using the app.UseIdentityServerAuthentication function. The following is the full Configure function.

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

    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
    {
        Authority = "http://localhost:5000",
        RequireHttpsMetadata = false,
        ApiName = "apiApp"
    });

    app.UseMvc();
}

Notice that the address of the of the authority must be specified (this will need to be the address the Identity Application is running on) as well as the ApiName matches the API Resource we added in the Config class of the Identity Application.

Next, in following the IdentityServer quickstart docs add a new IdentityController to the project. Just to be 100% clear this is just a test endpoint to show how to require authorization on a controller and isn’t something that is required to use IdentityServer. The controller has a single Get that returns the type and value of all the user’s claims.

[Route("api/[controller]")]
[Authorize]
public class IdentityController : Controller
{
    [HttpGet]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}

The [Authorize] attribute on the class is the bit that requires calls to this endpoint to have authorization. Keep in mind that the same attribute can be left off the class level and added to specific functions if the whole controller doesn’t require authorization.

Adding the [Authorize] attribute means that the IdentityServer middleware we added in the Startup class will validate the token associated with the request to make sure it is from a trusted issues and that it is valid for this API.

Client Application

For the Client application, I deviated from the samples a bit. Instead of just creating a new MVC application I used JavaScriptServices to generate an Angular (4) application. If you want detail on how that is done you can check out this post (yes it says Angular 2, but the newest version of JavaScriptServices now outputs Angular 4 and the steps haven’t changed). An Angular application is my end goal and why I made this deviation from the samples.

After the Client application has been created use NuGet to add the IdentityModel package. This package is to make interacting with the Identity Application simpler.

For this first go instead of actually interacting with the Identity Application from Angular I will be using it from MVC instead. The detail of interaction from Angular will come in a later post. The IdentityController is what does the interaction with both the Identity Application and the API Application interactions in this version of the client application. The following is the full IdentityController class.

public async Task<IActionResult> Index()
{
  var discovery = 
      await DiscoveryClient.GetAsync("http://localhost:5000");

  var tokenClient = new TokenClient(discovery.TokenEndpoint, 
                                    "clientApp", 
                                    "secret");
  var tokenResponse = 
      await tokenClient.RequestClientCredentialsAsync("apiApp");

  ViewData["tokenResult"] = tokenResponse.IsError 
                            ? tokenResponse.Error 
                            : tokenResponse.Json.ToString();

  var client = new HttpClient();
  client.SetBearerToken(tokenResponse.AccessToken);

  var apiResponse = 
      await client.GetAsync("http://localhost:5001/api/identity");
 
  ViewData["apiResult"] = apiResponse.IsSuccessStatusCode 
                          ? await apiResponse.Content.ReadAsStringAsync() 
                          : apiResponse.StatusCode.ToString();

  return View();
}

In the above, you can see the IdentityModel in action. Using the DiscoveryClient means the client application only needs to know about the root address of the Identity Application. TokenClient is being used to request a token from the Identity Application for the clientApp using the client secret which in this case is actually the word secret. Keep in mind in a real application secrets should be kept using the ASP.NET Core Secrets manager, see this related post. Also, take note that clientApp and secret are the values that were defined in the Config class of the Identity application.

The rest of the code is taking the token response and making a call to the API application with the response from both of those calls being stored in ViewData for display on the view associated with the controller.

The view is just an Index.cshtml file in the path Views/Identity. The following is the full view.

@{
    ViewData["Title"] = "Identity";
}

@ViewData["tokenResult"]
@ViewData["apiResult"]

It isn’t pretty, but the whole point of this controller and view is just for verification that the three applications are properly communicating with each other.

URL Configuration

In this setup, it is important that the URL for the Identity Application and API Application be fixed so they can be accessed by the client. In a more production level application, these values would at a minimum need to be in configuration. The following is the setup used for this solution.

  • Identity Application – http://localhost:5000
  • API Application – http://localhost:5001
  • Client Application – http://localhost:5002

There are a couple of ways to configure test values. The first is to open the project properties and select the Debug tab and set the App URL.

The second option is to go to the Program class for each project and add a UseUrls to the WebHostBuilder like the following.

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseUrls("http://localhost:5002")
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

Wrapping up

After going through the above process I now have a much better understanding of how the very basic setup using Identity Server should work. I hope if you made this far you found some helpful bits.

There is a bit of strangeness using Visual Studio to try and launch all three applications and can result in an error message if multiple of the projects are run in debug mode. For the most part, this can be worked around by only debugging one application at a time. It is a bit annoying at the beginning stages, but once an applications gets past that point I imagian that the Identity Application won’t require much debugging.

If there are any questions please leave a comment and I would be happy to try and help. The finished code can be found here. This basic example will be expanded over time and all the related entries can be found in the IdentityServer category.

Identity Server: Sample Exploration and Initial Project Setup Read More »

Visual Studio 2017 Error: The project doesn’t know how to run the profile IIS Express

I have a couple of computers I work between for the samples I use on this blog and when switching to between of them I got the following error last week.

The project doesn’t know how to run the profile IIS Express.

I verified the project would still run on the other computer with no issues. I also verified that on the computer with the issues the project would still work using dotnet run from the command line still worked.

Next, I went to verify the project properties. Here I noticed a strange thing on the computer with the error the Debug tab of the project properties was missing a lot of setting. The following is a screen shot of the computer with the issues.

And here is the same tab on the same project, but from a different computer.

The cause

After more time that I would like to admit I was able to track down the issue. On the computer with the issue, I often work on projects that are very large which tend to slow down Visual Studio pretty bad. In an effort to speed things up a bit I when through and disabled all the extensions that I could including the Microsoft Azure App Service Tools. Turns out that disabling the previous extension caused the Microsft ASP.NET and Web Tools extension to be disabled as well (with no warning).

The solution

The only way I was able to get the project to work properly was to enable both the Microsft ASP.NET and Web Tools extension AND the Microsoft Azure App Service Tools extension. I am not sure why the Microsft ASP.NET and Web Tools extension need the Microsoft Azure App Service Tools extension but based on my experience they are related in some way.

Visual Studio 2017 Error: The project doesn’t know how to run the profile IIS Express Read More »

Setting Up Visual Studio Code for Debugging ASP.NET Core

Visual Studio Code is a cross-platform source code editor from Microsoft. Out of the box, Code’s language support includes JavaScript, TypeScript, and Node. Using Codes extension system support is available for almost any language you want to use including C#, F#, Elixir, SQL, Swift, and Java. As of this writing, there are 734 language extensions available.

I have been using VS Code since it was first released after Build in 2015, but I have only been using it as an editor never taking advantage of the Debugging capabilities it has available. In this post, I am going to walk through everything that is needed to get a new ASP.NET Core with an Angular front end to run via VS Code’s debugger.

Test application

The first thing I did was to create a new application using JavaScriptServices specifically for this post. For instructions on how to use JavaScriptServices to generate an application check out this post.

On Windows, after the application has been generated and you are in the application directory you can use the following command to open the directory in VS Code.

code .

I am sure there is something similar on Linux and Mac, but I don’t have the environments to try on.

VS Code Overview

When VS Code opens you will see a view close to the following.

The icons down the left side of the screen are for Explorer (shows currently open directory and files), Seach, Source Control (git support is built in), Debug, and Extensions.

Debug

The Debug tab will be our focus so click on it which will take you to the following view.

Using the gear with red circle select .NET Core as the environment for the project.

If you don’t see .NET Core listed click More… and click install for the C# option.

After selecting an environment VS Code will add a launch.json file to the project. This file defines what happens when the start button is clicked in the debugger. At this point clicking the start button to run the application using the debugger will result in an error that Could not find the preLaunchTask ‘build’.

Next, click the Configure Task Runner option and select .NET Core.

This will add a task.json file with a build command that the launch.json is looking for. At this point, I had to restart VS Code to get it to properly pick up the new files. This seems to be an issue that will be fixed with the next release of VS Code and can be tracked using this issue.

After restart and trying to run the debugger again I ran into the error Run ‘Debug: Download .NET Core Debugger’ in the Command Palette or open a .NET project directory to download the .NET Core Debugger.

I ended up having to uninstall and reinstall the C# extension and then opening a C# file to get the debugger to download. If you are having this problem make sure and open a C# file before going as far as reinstalling the C# extension.

Hitting run in the debugger now give the error launch: launch.json must be configured. Change ‘program’ to the path to the executable file that you would like to debug.

To fix this issue click Open launch.json and you will find two places with the following.

"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>"

Change both places to point to the dll your application builds. In the case of my project named DebugTest the final version ended up being the following.

"program": "${workspaceRoot}/bin/Debug/netcoreapp1.1/DebugTest.dll"

Wrapping up

Debugging now works! Based on this post it would seem like debugging in VS Code is a big pain, but really after you get it set up once it just works. For new projects, you just have to let it add the

For new projects, you just have to let it add the launch.json and tasks.json and then set the path to your project’s assembly in launch.json. After that, you are ready to go.

I wait too long to figure this process out. I hope this helps you get started with debugging in VS Code.

Setting Up Visual Studio Code for Debugging ASP.NET Core Read More »

Identity Server: Introduction

In the SPA based sample applications, this blog has used so far user authentication has either been completely ignored in order to keep the examples simpler or the sites have used ASP.NET Core’s built in identity to encapsulate the whole SPA. In this post (or series of posts) I am going to share what I learn along the way of creating an Angular (2+) application that utilizes ASP.NET Core as its host/API/backend.

This post isn’t going to cover any code it is just going to be a lot of the information I gathered in the process of learning more about Identity Server.

Following are all the post in this series.

Identity Server: Introduction (this post)
Identity Server: Sample Exploration and Initial Project Setup
Identity Server: Interactive Login using MVC
Identity Server: From Implicit to Hybrid Flow
Identity Server: Using ASP.NET Core Identity
Identity Server: Using Entity Framework Core for Configuration Data
Identity Server: Usage from Angular

Identity Server

According to their docs IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core which enables Authentication as a Service, Single Sign-on, API Access Control and a Federation Gateway.

Obviously, that covers a lot of scenarios. The two that I am interested in are Authentication as a Service and the API Access Control which has driven my research which means that the other aspects of IdentityServer4 will not be included.

Official Samples

The IdentityServer GitHub account has a samples repo that contains a ton of examples. I have found the quickstart area of the repo to be the most helpful when starting out.

Based on all the quickstarts samples it looks like a typical setup involves a minimum of three projects. One for the API, one for the client and one for Identity Server. As you go through the samples the number of projects increase, but that is because of a wider range of scenarios that the sample is trying to cover.

References for learning

Damienbod has a whole series of blog posts related to IdentityServer4 and code to go along with it which can be found here. As a side note if you are interested in ASP.NET Core and you aren’t following damienbo you should be he has a ton of great content.

Blog posts
Videos

Identity Server Alternatives

Identity Server isn’t the only way to go there is a number of Software as a Service options that cover a lot of same scenarios. The following are some examples.

Auth0 – Check out the .NET Core related blogs by Jerrie Pelser
Stormpath
Amazon Cognito

Wrapping up

Obviously, I didn’t get a lot covered on how to actually do something with IdentityServer, but I wanted to share my starting point. This is an area I am going to continue digging it to and sharing information about as I learn more.

If you have any resources in this area please leave a comment below.

Identity Server: Introduction Read More »

Upgrading a JavaScript Services Application

As part of the ASP.NET Core Basics series of posts, JavaScript Services was used to create a couple of front end for a basic contacts API using Aurelia and Angular 2. Theses applications were created a few months ago and JavaScript Services has kept moving since then. This post is going to look at one strategy for taking an application created on an older version of JavaScript Services and update it to match the current version. This post will be following the upgrade of the Angular project from ASP.NET Core Basics repo with the starting point of the code being from this release.

The strategy

One of the considerations when doing this upgrade was getting the changes that happen on the ASP.NET Core side of the application and not just the JavaScript bits. In order to make sure that nothing was missed I decided to use JavaScript Services to generate a new application and use that to compare with the implementations in the existing application.

Create comparison application

This is going to assume JavaScript Services is already installed. If it isn’t this page has instructions or this post has sections that deal with creating a new application using JavaScript Services.

The update

Following is the files that changed during this update. This is also the list of files I would check anytime an upgrade needs to be done.

Angular.csproj
ClientApp/boot-client.ts
ClientApp/boot-server.ts
Program.cs
package.json
webpack.config.js
webpack.config.vendor.js

There were a fair amount of changes in the files listed above and instead of posting the code the differences can be found here. The previous diff didn’t contain the webpack.config files and those diffs can be found here and here.

After all the files have been updated make sure to run the following command from a command prompt in your project directory to make sure webpack has vendor related items regenerated.

webpack --config webpack.config.vendor.js

Wrapping up

This post is a lighter on the details that I do most of the time, but this type of upgrade would just have been a wall of code and not been overly useful and the commits on GitHub are a much better guide to what the upgrade looked like. My feeling is that over time the number of changes going forward may end up being smaller and easier to integrate.

Both the Aurelia and Angular projects have been upgraded and the final version of the code can be found here.

Upgrading a JavaScript Services Application Read More »

Entity Framework Core with SQLite Migration Limitations

This is part of what has turned into a series on Entity Framework Core with SQLite. The other parts can be found below.

Entity Framework Core with SQLite
Entity Framework Core Errors Using Add-Migration
Entity Framework Core with SQLite Scaffolding

The starting point of the code for this post can be found here.

Migration Limitations when using SQLite

SQLite’s ALTER TABLE is limited which in turn limits what Entity Framework Core can do via a migration. The official docs on the subject can be found here. These limitations are on the Entity Framework Team’s list of issues as an open enhancement and can be tracked here.

As long as you are just adding new tables or columns you would never notice the limitation, but if you have spelling problems like I do then the need to rename a column can be important. Thankfully things like ReSpeller (link is to the pro page, but a free version is available in ReSharpers extension manager) help with my spelling issues.

Unsupported example with a column rename

As an example of how to handle a migration that isn’t supported, we are going to rename the State property of the Contact class to Subregion.

Rename property on the model

Open the Contact class which can be found in the Models directory and make the following change.

Before:
public string State { get; set; }

After:
public string Subregion { get; set; }
Add a migration

With the property name change using the following command in the Package Manager Console to create a new migration.

Add-Migration RenameContactStateToSubregion -c ContactsDbContext

Which produces the following migration class.

public partial class RenameContactStateToSubregion : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "State",
            table: "Contacts",
            newName: "Subregion");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "Subregion",
            table: "Contacts",
            newName: "State");
    }
}
Error trying to apply the migration

As expected when an attempt to apply the above migration results in the following exception.

System.NotSupportedException: SQLite does not support this migration operation (‘RenameColumnOperation’). For more information, see http://go.microsoft.com/fwlink/?LinkId=723262.

Modify migration to manually rename the column

Searching for how to rename a column in SQLite will turn up a lot of results including this from the official docs and answers like this on StackOverflow. The gist of the how to do a rename is to create a new table with the desired schema, copy the data from the original table, drop the old table, and finally rename the new table to match the original name.

Now knowing the process the migration above can be modified to apply SQL directly instead of using Entity Framework Core to generate the SQL. This can be done by using the Sql function of the MigrationBuilder class. The following is the resulting migration.

public partial class RenameContactStateToSubregion : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql(
            @"PRAGMA foreign_keys = 0;

              CREATE TABLE Contacts_temp AS SELECT *
                                            FROM Contacts;
              
              DROP TABLE Contacts;
              
              CREATE TABLE Contacts (
                  Id         INTEGER NOT NULL
                                     CONSTRAINT PK_Contacts PRIMARY KEY AUTOINCREMENT,
                  Address    TEXT,
                  City       TEXT,
                  Email      TEXT,
                  Name       TEXT,
                  Phone      TEXT,
                  PostalCode TEXT,
                  Subregion  TEXT
              );
              
              INSERT INTO Contacts 
              (
                  Id,
                  Address,
                  City,
                  Email,
                  Name,
                  Phone,
                  PostalCode,
                  Subregion
              )
              SELECT Id,
                     Address,
                     City,
                     Email,
                     Name,
                     Phone,
                     PostalCode,
                     State
              FROM Contacts_temp;
              
              DROP TABLE Contacts_temp;
              
              PRAGMA foreign_keys = 1;");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
    }
}

You will notice that I didn’t bother doing the Down function, but the same idea would apply when trying to undo a migration. SQLiteStudio or similar tools can be used to generate the SQL above if SQL isn’t something you want to deal with.

Fix other references to the renamed field

This isn’t really the topic of this post, but I wanted to throw in a reminder that after a rename like this there are places that will need to be updated that the tooling may not have picked up. For example, make sure all your views are using the new column as well as any bind statements in your controllers.

Wrapping up

The first time I hit the need to rename a column and it resulted in an exception it was extremely frustrating. Over time as I learned what the tooling around SQLite provides it has become less of an issue. I look forward to seeing what the Entity Framework team does in the future around this issue. The finished code can be found here.

Entity Framework Core with SQLite Migration Limitations Read More »

Entity Framework Core with SQLite Scaffolding

This is the third in what is turning into a series of post about using SQLite with Entity Framework Core. This post is going to cover adding a migration, scaffolding a controller and related views, and a few things that are harder to do using SQLite. The following are the first two post.

Entity Framework Core with SQLite
Entity Framework Core Errors Using Add-Migration

Adding Model, DbContext, Controller, and Views

If you have any experience with Entity Framework Core or have read any of my past entries on the subject this section is going to repeat some of the same information, but I am including it so someone who is looking for a full example will have it.

Model

In the Models folder add a Contact class similar the following.

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; }
}
DbContext

In the Data folder add a ContactsDbContext that inherits from DbContext. The following is an example that auto applies migrations to a database, if you don’t need that functionality it can be dropped out.

public sealed class ContactsDbContext : DbContext
{
    private static bool _created;

    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext(DbContextOptions<ContactsDbContext> options)
        : base(options)
    {
        if (_created) return;
        Database.Migrate();
        _created = true;
    }
}

Now that the application has a model and a related DbContext the following can be used to add a migration that will create a Contacts in the SQLite database. Run from the Package Manager console.

Add-Migration AddContacts -Context ContactsDbContext

Add-Migration is a Powershell command to add a migration (surprise!), AddContacts is the name of the migration and -Context ContactsDbContext is an argument that lets the command know which DbConext to use. The Context is only needed if your application has more than one DbContext.

Controller and Views

With the above complete Visual Studio provides some tooling that makes it very fast to create a controller with views for listing, adding, editing, and deleting items. To begin right-click on the Controllers folder and select Add > New Scaffolded Item.

Select the MVC Controller with views, using Entity Framework option and click Add.

On the next dialog use the drop downs to select a model class and a data context class. Then verify the controller name and click add.

When the process completes the following items will have been added to your project.

Controllers
 - ContactsController.cs
Views
 - Contacts
   - Create.cshtml
   - Delete.cshtml
   - Details.cshtml
   - Edit.cshtml
   - Index.cshtml
Add to nav bar

To add a link to the new section of the app to the nav bar open the _Layout.cshtml in the Views/Shared/ directory. The following is the section of the file that needs to be changed to add an item to the nav bar.

<ul class="nav navbar-nav">
    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
    <li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>

Specifically, the following line was added to provide access to the contact list page.

<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts</a></li>

Wrapping up

With the above, the application will be runnable. The code for this post can be found here. The next post in this series will cover the limitations of migrations when using SQLite with Entity Framework Core.

 

Entity Framework Core with SQLite Scaffolding Read More »

Entity Framework Core Errors Using Add-Migration

I started off trying to expand my sample from last week’s post and hit some issues when trying to add a migration for a new DbContext.

The Setup

I added the following DbContext that only has one DbSet and auto applies migrations in the constructor.

using EfSqlite.Models;
using Microsoft.EntityFrameworkCore;

public sealed class ContactsDbContext : DbContext
{
    private static bool _created;

    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext(DbContextOptions<ContactsDbContext> options)
        : base(options)
    {
        if (_created) return;
        Database.Migrate();
        _created = true;
    }
}

The command

Using Visual Studio’s Package Manager Console I ran the following command.

Add-Migration AddContacts -Context ContactsDbContext
Error 1 – No parameterless constructor

The above command resulted in the following error.

No parameterless constructor was found on ‘ContactsDbContext’. Either add a parameterless constructor to ‘ContactsDbContext’ or add an implementation of ‘IDbContextFactory<ContactsDbContext>’ in the same assembly as ‘ContactsDbContext’.

I read the first sentence and added a parameterless constructor to ContactsDbContext. I did think it was strange that a parameterless constructor wasn’t required the other contexts I had written in the past, but the error said to add a parameterless constructor so that is what I did.

Error 2 – System.InvalidOperationException: No database provider has been configured for this DbContext

Now having a parameterless constructor I ran the Add-Migration command again and was greeted with the following error.

System.InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.

The second error forced me to step back and think more about what the problem was as it didn’t have an action I could take as the first sentence, which is, of course, my fault for not fully digesting what the error was saying.

The fix

The bit I was missing was the fact that I hadn’t added the following to the ConfigureServices function of the project’s Startup class.

services.AddDbContext<ContactsDbContext>(options =>
    options.UseSqlite(Configuration.GetConnectionString("Sqlite")));

With the above added I removed the parameterless constructor from ContactsDbContext and was able to successfully run the add migration command again.

Wrapping up

The moral of the story is to actually read the full error message before running off and trying to fix the problem. The second error message saying “using AddDbContext on the application service provider” is what triggered me to head in the right direction.

This was also a good reminder that tools like the ones used by Add-Migration can/do compile the project they are being used on in order to have enough context to perform their tasks.

Entity Framework Core Errors Using Add-Migration Read More »

Entity Framework Core with SQLite

All the applications used as examples for ASP.NET Core and Entity Framework Core from this site so far used database running SQL Server/SQL Express. In addition to the Microsoft-based SQL databases, Entity Framework Core has support for a number of other database providers. This post is going to look at using SQLite. A full list of the support database providers can be found here.

Starting point

Using Visual Studio 2017 I started with a new ASP.NET Core project using Individual User Accounts which ensured all the Entity Framework Core bits were present. The template in RC 4 used packages based on the Core 1.0.3 which I upgraded to 1.1.0. The project at this point can be found here.

Just a side note this project was created when Visual Studio 2017 was at the RC 4 stage. This code associated with this post will be updated when Visual Studio 2017 is released.

Naming warning

As you will be able to see with the structure of the solution I started this work using the project name SQLite. With this project name, it was impossible to get the SQLite package to install. If you see something like the following renaming your project should get you running.

Cycle detected: 
   Sqlite (>= 1.0.0) -> Microsoft.EntityFrameworkCore.Sqlite (>= 1.1.0) -> Microsoft.Data.Sqlite (>= 1.1.0) -> SQLite (>= 3.13.0)

This issue is where I found out what the problem was.

Add SQLite Packages

Right-click on the project file and click Manage NuGet Packages.

Select Browse and in the search box enter “Microsoft.EntityFramework.Sqlite” and install the two packages that are found.

Remove SqlServer Packages

While still in the Manage NuGet Packages screen click on the Installed tab. Select and uninstall the following packages.

Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer.Design

Configuration changes

Open appsettings.json and in the ConnectionStrings delete the line for DefaultConnection. Next, in the same section add a line for a SQLite connection string. The following is the result.

"ConnectionStrings": {
  "Sqlite": "Data Source=Database.db"
}

The above will expect the database file to be in the same location as the application is running. For a debug build the database file can be found in the \bin\Debug\netcoreapp1.0\ directory of the project.

Startup changes

The final location to change is in the ConfigureServices function of the Startup class. The following shows the addition of the application DB context before and after the changes.

Before:
services
  .AddDbContext<ApplicationDbContext>(options =>  options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
 
After:
services
  .AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(Configuration.GetConnectionString("Sqlite")));

Wrapping up

The application is now runnable using SQLite as its backing data store. At this point, the only thing using data access is related to identity. The first time an attempt is made to access the database you may be prompted to apply migrations.

I have been using SQLite Studio to view the data in my database if you have that need outside of the application it does a good job.

The code in its final state can be found here.

Entity Framework Core with SQLite Read More »

ASP.NET Core Conversion to csproj with Visual Studio 2017 and update to 1.1.1

On March 7th Visual Studio 2017 was released bring the ASP.NET Core tools preview. ASP.NET Core 1.1.1 was also released. This post is going to cover converting the project from my MailGun post from being project.json based to csproj as well as migrating from the project from ASP.NET Core 1.0.2 to 1.1.1. Here is the project as it stood before I made any changes.

Visual Studio 2017

The first step is to get a version of Visual Studio 2017 (VS 2017) installed. The download page can be found here. Make sure to grab the community edition if you are looking for a free fully-featured IDE option. Check out this blog post from Microsoft on the many new features Visual Studio 2017 brings.

The installer for VS 2017 has changed a lot from previous versions. The way it works now is you select the workload you use and it only installs the bit it has to to keep the size of install down. The following is a screen shot from my install. I have a lot more workloads checked that is needed for just an ASP.NET Core application. At a minimum make sure the “ASP.NET and web development” workload gets installed. If you are interested in cross-platform development scroll to the bottom and also check “.NET Core cross-platform development”.

Project conversion

When you open the solution in VS 2017 it will prompt you to do a one-way upgrade.

After the conversion is complete a migration report will open. Below is mine. I had no issues, but if there were any this report should give you some idea of how they should be addressed.

As part of the conversion process, the following file changes happened.

Deleted:
global.json
ASP.NET-Core-Email.xproj
project.json

Added:
ASP.NET-Core-Email.csproj

That is all there is to the conversion. The tooling takes care of it all and your project should keep work just as before. The sample project post conversion can be found here.

Migration from 1.0.x to 1.1.1

The migration is almost as simple as the project conversion. In the solution explorer right click on the project to be migrated and select Properties.

Find the Target framework selection and select .NETCoreApp 1.1. Then save your solution.

Next, open the NuGet Package Manager. It can be by right click on the project and selecting Manage NuGet Packages or from the Tools > NuGet Package Manager > Manage NuGet Packages for Solution.

Select the Updates tab and update all the related packages to 1.1.1 and click the Update button.

If you want a specific list of all the package changes check out the associated commit.

The only other change needed is in the constructor of the Startup class.

Before:
builder.AddUserSecrets();

After:
builder.AddUserSecrets<Startup>();

Wrapping up

After all the changes above your solution will be on the latest released bits. Having been following releases since beta 4 I can tell you this is one of the easiest migration so far. I may be partial, but .NET and Microsoft seem to be getting better and better over the last couple of years.

I am going to leave you with a few related links.

ASP.NET Core 1.1.1 Release Notes
Announcing New ASP.NET Core and Web Dev Feature in VS 2017
Project File Tools – Extension for IntelliSense in csproj
Razor Language Services – Extension for tag helper Intellisense

ASP.NET Core Conversion to csproj with Visual Studio 2017 and update to 1.1.1 Read More »