Skip to content

myraninkero/MovieDatabaseApi

Repository files navigation

MovieDatabaseApi - REST API in ASP.NET Core (.NET 9)

This project is a REST API built with ASP.NET Core (.NET 9) using Minimal API.

It includes:

  • Layered architecture (API, Services, Domain, Data)
  • EF Core Code First with PostgreSQL
  • Seed data
  • Database-backed users with hashed passwords
  • Global exception handling middleware instead of try/catch blocks in each endpoint
  • JWT authentication and role-based authorization
  • Swagger/OpenAPI and Postman collection with scripts

Architecture

  • API/ - Endpoints.cs, DTO.cs
  • Data/ - AppDbContext.cs, Entities/, Repositories/
  • Domain/ - Models/, Repositories/
  • Services/ - business logic
  • Exceptions/ - ApiExceptions.cs
  • Migrations/ - EF Core migrations

Quick Start

  • Have .NET 9 SDK and Docker installed.
  • Have Postman installed for API testing and Swagger exploration.
  • Optional: Have DataGrip installed for database inspection.
  1. Place yourself in MovieDatabaseApi/ with the CMD (terminal) and run the following:
dotnet restore
  1. Start PostgreSQL with Docker Compose
docker compose up -d
  1. Apply migration
dotnet ef database update
  1. Start the API
dotnet run

Database and Seed Data

  • Connection string is configured in appsettings.json
  • Seed data for genres/movies/reviews is configured in Data/AppDbContext.cs (HasData())
  • Seeded auth users (admin, user) are created on startup in Program.cs
  • Migration files are in Migrations/

JWT and Roles

Token endpoint:

  • POST /api/auth/token

The token endpoint validates users from the users table. Passwords are stored as hashes using PasswordHasher<TUser>.

Seeded users:

  • admin / admin123 -> role Admin
  • user / user123 -> role User

Request body for admin token:

{
  "username": "admin",
  "password": "admin123"
}

Request body for user token:

{
  "username": "user",
  "password": "user123"
}

Admin-protected endpoints:

  • POST /api/movies
  • PUT /api/movies/{id}
  • DELETE /api/movies/{id}
  • POST /api/genres

Authenticated endpoint (User or Admin):

  • POST /api/movies/{movieId}/reviews

Endpoint Overview

  • GET /api/movies
  • GET /api/movies/{id}
  • POST /api/movies (Admin)
  • PUT /api/movies/{id} (Admin)
  • DELETE /api/movies/{id} (Admin)
  • GET /api/genres
  • POST /api/genres (Admin)
  • GET /api/movies/{movieId}/reviews
  • POST /api/movies/{movieId}/reviews (User or Admin)
  • POST /api/auth/token

Using Swagger

Swagger URL: http://localhost:5052/swagger

  1. Run the API dotnet run
  2. Open Swagger URL
  3. Use POST /api/auth/token (with the admin request body above) to get access_token and copy it (without quotes) from the response body
  4. Click Authorize in Swagger (should be in the top right corner) and paste your access_token and close the popup window
  5. Test protected endpoints (POST/PUT/DELETE). You can now manually enter request bodies or use the "Try it out" feature in Swagger to send requests and see responses.
  6. You can also test (with the user request body above) the user-protected endpoint (POST /api/movies/{movieId}/reviews) by authenticating with the user credentials and repeating steps 3-5.

Note:

The JSON contract uses snake_case (for example, release_year and genre_id). To ensure Swagger shows the same field names as the API, DTO fields in API/DTO.cs are annotated with JsonPropertyName.

Using Postman

Collection file:

  • postman/MovieDatabaseApi.postman_collection.json

How to use:

  1. Import collection in Postman
  2. Set collection variable baseUrl to your running API URL (in this case http://localhost:5052)
  3. Run from top to bottom in this order:
    • Authenticate as Admin
    • Authenticate as User
    • Create Genre as Admin
    • Create Movie as Admin
    • Update Movie as Admin
    • Create Review for Movie as User
    • List Reviews for Movie
    • Create Review for Movie (No Token)
    • Delete Movie as Admin
  4. You can also right‑click the MovieDatabaseApi collection and choose Run to execute the entire collection with the included test scripts.

Notes:

  • Collection uses variables for token and created IDs
  • Login is validated against seeded users in the database
  • If a run fails, clear collection variables and run again from the first request

Using DataGrip

You can inspect PostgreSQL tables directly in DataGrip.

Connection values:

  • Host: localhost
  • Port: 5432
  • Database/User/Password: from docker-compose.yml and/or your connection string in appsettings.json

Setup with CMD (if you forgot to do that in the beginning):

docker compose up -d
dotnet ef database update

Then in DataGrip:

  1. Create a new PostgreSQL data source
  2. Enter host/port/database/user/password
  3. Connect and open tables:
    • genres
    • movies
    • reviews
    • users

Quick SQL checks:

select * from genres;
select * from movies;
select * from reviews;
select username, role, created_at from users;

Have fun!
Marcus Myran Inkerö
SYS25D
Signing out

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages