read

Microsoft have slowly been making progress with their cross platform efforts and .NET Core is starting to look like it might be interesting. In this post we look at integrating a .NET Core Web API with PostgreSQL running a mac (this code should also work on Linux).

You can download the source code for this post from here (GitHub)

First check that you have the dotnet command line installed.

dotnet --version

If you don’t have it yet then head off to here to download and install it.

Once you are all set up we can create a new project. You can see the types of projects you can create by running:

dotnet new --help

Templates                 Short Name      Language      Tags          
----------------------------------------------------------------------
Console Application       console         [C#], F#      Common/Console
Class library             classlib        [C#], F#      Common/Library
Unit Test Project         mstest          [C#], F#      Test/MSTest   
xUnit Test Project        xunit           [C#], F#      Test/xUnit    
ASP.NET Core Empty        web             [C#]          Web/Empty     
ASP.NET Core Web App      mvc             [C#], F#      Web/MVC       
ASP.NET Core Web API      webapi          [C#]          Web/WebAPI    
Solution File             sln                           Solution      

Let’s create a new Web API project:

dotnet new webapi -n MyFirstWebAPI
cd MyFirstWebAPI/
dotnet restore

This will create a new application MyFirstWebAPI, we then cd into the new project and restore all the packages the application requires.

We can the current set of packages by looking in MyFirstWebAPI.csproj

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

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
  </ItemGroup>

</Project>

If we look in the Controllers folder we can see that they’ve given us a default api controller called ValuesController.

Lets run up the application and try it out.

dotnet run

Hosting environment: Production
Content root path: /Users/chrisgreening/Work/dotnetcore/MyFirstWebAPI
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Let’s see if we can retrieve the list of values from ValuesController (I’m using jq to pretty print my JSON - you can install this using brew install jq)

curl localhost:5000/api/values -sS | jq

[
  "value1",
  "value2"
]

We’ve got a basic API server working, let’s try hooking it up to a PostgreSQL database. First lets get a database set up for our experimentation (I’m assuming you have either PostgreSQL installed locally or available in a docker environment - I’d recommend getting it set up in docker):

psql -U postgres
CREATE ROLE dotnet_user with encrypted password 'secret' LOGIN;
CREATE DATABASE dotnet_test with owner dotnet_user;

Now we need to add some new packages to our project. Let’s add them via the command line:

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.Design

There is one small change we need to make to our csproj file - we need to change the reference to the Microsoft.EntityFrameworkCore.Tools.DotNet package from a PackageReference to a DotNetCliToolReference. This will expose the dotnet ef command to us. Edit MyFirstWebAPI.csproj and move the package into it’s own group and change it to DotNetCliToolReference.

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="1.1.0" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
  </ItemGroup>
</Project>

Now run the following command to make sure we have all the packages installed:

dotnet restore

Let’s now setup our database connection in our app settings. Open up the file appsettings.json in the root of the project and modify it so it contains a connection string to the database we created earlier:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "ConnectionStrings": {
    "DATABASE_URL": "User ID=dotnet_user;Password=secret;Host=localhost;Port=5432;Database=dotnet_test;Pooling=true;"
  }
}

Let’s create some entities - we’ll create a simple Test entity - create a folder called Entities and a file called Test.cs:

using System;

namespace MyFirstWebAPI.Entities
{
  public class Test
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
  }
}

We can now create our DbContext - this is the class that gets the Entity Framework up and running. Create a new folder Database and a file ApplicationDbContext.cs

using System;
using Microsoft.EntityFrameworkCore;

namespace MyFirstWebAPI.Database
{
  public class ApplicationDbContext : DbContext
  {
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }
    public DbSet<Entities.Test> TestRecords { get; set; }
  }
}

We now need to add our ApplicationDbContext to the dependency injection framework and configure the connection string. Open up Startup.cs. Add a reference to EntityFrameworkCore

using Microsoft.EntityFrameworkCore;

And in the ConfigureServices method add the following code to setup our ApplicationDbContext:

var sqlConnectionString = Configuration.GetConnectionString("DATABASE_URL");
services.AddDbContext<Database.ApplicationDbContext>(options =>
    options.UseNpgsql(
        sqlConnectionString,
        b => b.MigrationsAssembly("MyFirstWebAPI")
    )
);

We should now be in a position to generate a database migration to add our new entity to the database.

dotnet ef migrations add "Create Test Entity"

This should have created us a new file Migrations/XXXX_Create Test Entity.cs which will contain code for and Up method for creating our new table and a Down method for destroying our new table.

Let’s now run the migration to update our database.

dotnet ef database update

If we now look in our database we should see the new table:

\connect dotnet_test
\d "TestRecords"
                             Table "public.TestRecords"
   Column    |  Type   |                         Modifiers                          
-------------+---------+------------------------------------------------------------
 Id          | integer | not null default nextval('"TestRecords_id_seq"'::regclass)
 Description | text    | 
 Name        | text    | 
Indexes:
    "PK_TestRecords" PRIMARY KEY, btree (Id)

Let’s now hook up our ValuesController to our DbContext. We will use the dependency injection system to automatically get a reference to the ApplicationDbContext. Modify the ValuesController class so that it has a member variable and a constructor:

public class ValuesController : Controller
{
  Database.ApplicationDbContext dbContext;

  public ValuesController(Database.ApplicationDbContext dbContext)
  {
    this.dbContext = dbContext;
  }

We’ll wire up the Get method to get all the Test entities:

[HttpGet]
public IEnumerable<Entities.Test> Get()
{  
    return dbContext.TestRecords;
}

The get by id method:

[HttpGet("{id}")]
public Entities.Test Get(int id)
{
    return dbContext.TestRecords.Where(t => t.Id == id).FirstOrDefault();
}

The post:

[HttpPost]
public Entities.Test Post([FromBody]Entities.Test value)
{
    dbContext.TestRecords.Add(value);
    dbContext.SaveChanges();
    return value;
}

The put method:

[HttpPut("{id}")]
public Entities.Test Put(int id, [FromBody]Entities.Test value)
{
    var entity = dbContext.TestRecords.Where(t => t.Id == id).FirstOrDefault();
    entity.Name = value.Name;
    entity.Description = value.Description;
    dbContext.SaveChanges();
    return entity;
}

And finally the delete method

[HttpDelete("{id}")]
public Entities.Test Delete(int id)
{
    var entity = dbContext.TestRecords.Where(t => t.Id == id).FirstOrDefault();
    dbContext.TestRecords.Remove(entity);
    dbContext.SaveChanges();
    return entity;
}

Now lets try out our new API:

dotnet run
Hosting environment: Production
Content root path: /Users/chrisgreening/Work/dotnetcore/MyFirstWebAPI
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

If we list our objects we should get an empty array as the database is empty:

curl localhost:5000/api/values -sS | jq
[]

Let’s create some objects:

curl localhost:5000/api/values -H "Content-Type: application/json" -X POST -d '{"Name": "Bob", "Description": "A cool guy"}' -sS | jq 
{
  "id": 1,
  "name": "Bob",
  "description": "A cool guy"
}
curl localhost:5000/api/values -H "Content-Type: application/json" -X POST -d '{"Name": "Jim", "Description": "Good chap"}' -sS | jq 
{
  "id": 2,
  "name": "Jim",
  "description": "Good chap"
}
curl localhost:5000/api/values -H "Content-Type: application/json" -X POST -d '{"Name": "Chris", "Description": "A bit bananas"}' -sS | jq 
{
  "id": 3,
  "name": "Chris",
  "description": "A bit bananas"
}
curl localhost:5000/api/values -sS | jq
[
  {
    "id": 1,
    "name": "Bob",
    "description": "A cool guy"
  },
  {
    "id": 2,
    "name": "Jim",
    "description": "Good chap"
  },
  {
    "id": 3,
    "name": "Chris",
    "description": "A bit bananas"
  }
]

Let’s check our put command:

curl localhost:5000/api/values/3 -H "Content-Type: application/json" -X PUT -d '{"Name": "Chris", "Description": "What a guy!"}' -sS | jq
{
  "id": 3,
  "name": "Chris",
  "description": "What a guy!"
}
curl localhost:5000/api/values/3 -sS | jq
{
  "id": 3,
  "name": "Chris",
  "description": "What a guy!"
}

And let check we can delete

curl localhost:5000/api/values/3 -X DELETE
curl localhost:5000/api/values/2 -X DELETE
curl localhost:5000/api/values -sS | jq
[
  {
    "id": 1,
    "name": "Bob",
    "description": "A cool guy"
  }
]

We’ve now got a nice little server running .Net core talking to a PostgreSQL database.

Why not subscribe to my mailing list - I'll send out regular emails with new content (don't worry I won't spam you!)

* indicates required
Blog Logo

Chris Greening


Published

Image

Chris Greening

Blogging about random stuff

Back to Overview