Skip to content

HarrisonSlater/Harri.SchoolDemoAPI

Repository files navigation

Harri.SchoolDemoAPI - ASP.NET Core 8.0 REST API

Harri.SchoolDemoAPI is a demo REST API built with ASP.NET Core 8.0 that manages students, schools, and applications. It showcases modern .NET backend development practices, including comprehensive automated testing, containerization, structured logging, and CI/CD integration with Azure DevOps.

Also see a front-end Blazor WASM SPA developed for this API here: Blazor Admin UI

Automated Testing

An emphasis on comprehensive automated testing has been used when developing this demo API.

Included are Unit, Contract, Integration, and E2E test projects. See the full Test README here

All test projects are run as part of the Azure DevOps pipeline as part of the Build stage (for Unit and Contract) or the 'Deploy & Test' stage (For Integration and E2E), and are run in-agent.

đźš§ Work In Progress - API

So far the /students/ API is complete: StudentsApiController.cs

Table of Contents

Project Diagram

flowchart LR
Client[C# Client]
SQL[(SQL)]

subgraph API[REST API]
direction LR
Controller---Service---Repository
end
Client-- Network ---Controller
Repository-- Network ---SQL

Loading

JSON API Request/Response examples

Operation Resource
POST /students
GET /students/{sId}
PUT /students/{sId}
PATCH /students/{sId}
DELETE /students/{sId}
GET /students

POST /students

Request:

POST /students

Request Body:

{
  "name": "Student Name"
}

or with optional GPA:

{
  "name": "Student Name",
  "GPA": 3.52
}

Response
containing created student ID:

HTTP/1.1 200 OK
Content-Type: application/json

1348

GET /students/{sId}

Request:

GET /students/1348

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "sId": 1348,
  "name": "Student Name",
  "GPA": 3.52
}

PUT /students/{sId}

(Update entire student record)

Request:

PUT /students/1348

Request Body:

{
  "name": "Student Name Updated",
  "GPA": 3.65
}

Response

HTTP/1.1 200 OK

PATCH /students/{sId}

(Update partial student record)

Request:

PATCH /students/1348

Request Body:

{
  "name": "Student Name Patched"
}

Response
containing modified student record

HTTP/1.1 200 OK
Content-Type: application/json

{
  "sId": 1348,
  "name": "Student Name Patched",
  "GPA": 3.65
}

DELETE /students/{sId}

Request:

DELETE /students/1348

Response

HTTP/1.1 200 OK

GET /students (Paginated, Sortable, Query API)

By Id

Request:

GET /students?sId=1

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [
    {
      "sId": 1,
      "name": "Olivia Jackson",
      "GPA": 1.43
    },
    {
      "sId": 10,
      "name": "Harper Jones",
      "GPA": 3.94
    },
    {
      "sId": 11,
      "name": "Noah Lopez",
      "GPA": 1.78
    },
    {
      "sId": 12,
      "name": "Liam Taylor",
      "GPA": 3.65
    },
    {
      "sId": 13,
      "name": "Emma Davis",
      "GPA": 1.72
    },
    {
      "sId": 14,
      "name": "Amelia Johnson",
      "GPA": 3.62
    },
    {
      "sId": 15,
      "name": "Harper Taylor",
      "GPA": 1.24
    },
    {
      "sId": 16,
      "name": "Lucas Thomas",
      "GPA": 3.42
    },
    {
      "sId": 17,
      "name": "Ava Rodriguez",
      "GPA": 3.15
    },
    {
      "sId": 18,
      "name": "Benjamin Lopez",
      "GPA": 3.69
    }
  ],
  "page": 1,
  "pageSize": 10,
  "totalCount": 328,
  "totalPageCount": 33,
  "hasNextPage": true,
  "hasPreviousPage": false
}

By Name

Request:

GET /students?name=Ethan%20S&page=1&pageSize=3

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [
    {
      "sId": 124,
      "name": "Ethan Smith",
      "GPA": 2.84
    },
    {
      "sId": 137,
      "name": "Ethan Smith",
      "GPA": 3.12
    },
    {
      "sId": 956,
      "name": "Ethan Smith",
      "GPA": 1.35
    }
  ],
  "page": 1,
  "pageSize": 3,
  "totalCount": 3,
  "totalPageCount": 1,
  "hasNextPage": false,
  "hasPreviousPage": false
}

By GPA Greater Than, sorted

Request:

GET /students?GPA.Gt=2&orderBy=ASC&sortColumn=GPA&page=1&pageSize=4

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [
    {
      "sId": 324,
      "name": "Harper Johnson",
      "GPA": 2.01
    },
    {
      "sId": 874,
      "name": "Aria Jackson",
      "GPA": 2.03
    },
    {
      "sId": 975,
      "name": "Charlotte Jackson",
      "GPA": 2.03
    },
    {
      "sId": 853,
      "name": "Charlotte Thomas",
      "GPA": 2.04
    }
  ],
  "page": 1,
  "pageSize": 4,
  "totalCount": 694,
  "totalPageCount": 174,
  "hasNextPage": true,
  "hasPreviousPage": false
}

Running the SchoolDemo REST Web API

You have three options for running this web API,

  1. Build it from source and run with dotnet sdk. See Building from source below

  2. Build a docker container and run. See Building container from source below

  3. Pull and run a docker container. See Running from container below

    For all options above you will also need to pull and run the database container

Building from source

Use the included build scripts in the root of the repo or build in Visual Studio

Windows

PowerShell

./build.bat

CMD

build

Linux

./build.sh

Running from source

The build script then prompts you to run using

dotnet run --project src\Harri.SchoolDemoAPI\Harri.SchoolDemoAPI.csproj

The API will be accessible via http://localhost:8080 by default

Also make sure to set up the database or the API will return 500 Internal server error Running the database from container

Building container from source

Build the container locally run:

docker build -t schooldemoapi -f .\src\Harri.SchoolDemoAPI\Dockerfile .

Running from container

If you built the container yourself locally as above run:

docker run -it -p 8080:8080 --name schooldemoapi schooldemoapi


If you don't want to build the container you can pull the latest main branch linux container image from the DockerHub harri-schooldemoapi repository

docker pull harrisonslater/harri-schooldemoapi:latest

And run

docker run -it -p 8080:8080 --name schooldemoapi harrisonslater/harri-schooldemoapi:latest

The API will be accessible via http://localhost:8080 or you can specify a different port in the docker run command above like 5000:8080

Running the database from container

The database required by the SchoolDemoAPI is available as a linux container image prefilled with student, school, and application data from the DockerHub harri-schooldemosql-database repository

docker pull harrisonslater/harri-schooldemosql-database:latest

And to run the database container:

docker run -e "MSSQL_SA_PASSWORD=p@ssw0rd" -p 1433:1433 -d harrisonslater/harri-schooldemosql-database:latest

Build pipeline

Azure DevOps pipeline defined in yaml

A successful pipeline run based on main looks like: image

Pipeline deploying

In a real world pipeline Deploy & Test would be separate stages where Deploy actually deploys to an environment. In this pipeline 'Deploy' just runs the container image / .NET dll in-agent. This is done to remove ongoing hosting costs

Logging using Application Insights & Serilog

Logging accessible via standard ILogger interface

.UseHttpLogging(); is used for request and response body logging

Serilog is fully configured in the appsettings.json

Other than console and debug logs this also logs to:

  • Log file: /Logs/log.txt
  • Application Insights: set up for local usage within visual studio
    • Custom events are logged via Serilog
  • SEQ: free personal edition that can be run in a container

For App insights and SEQ:

  • Requests and responses with body are logged as custom events
    • In a production scenario you probably don't want to do this as sensitive data may be logged

Health check endpoint /health

Response implemented with AspNetCore.HealthChecks.UI.Client/UIResponseWriter.cs to return a result like:

{
  "status": "Healthy",
  "totalDuration": "00:00:00.0858619",
  "entries": {
    "sql": {
      "data": {},
      "duration": "00:00:00.0856835",
      "status": "Healthy",
      "tags": []
    }
  }
}

Also included is a RestSharp client in a separate project Harri.SchoolDemoAPI.HealthCheckClient along with consumer driven contract tests

Nuget packages used

About

School Admin Demo .NET 8 REST API

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages