From e47449ce63e027bad61ce523fa2b2d508f016c84 Mon Sep 17 00:00:00 2001 From: Joao Ferreira Date: Sun, 8 Feb 2026 10:50:33 -0300 Subject: [PATCH 1/3] feat: adding Reading.cs model and Get, GetById and Post method --- AirAware/Controllers/ReadingController.cs | 69 +++++++++++++++++++ AirAware/Data/AppDbContext.cs | 1 + AirAware/Models/Reading.cs | 15 ++++ AirAware/ViewModels/CreateReadingViewModel.cs | 14 ++++ 4 files changed, 99 insertions(+) create mode 100644 AirAware/Controllers/ReadingController.cs create mode 100644 AirAware/Models/Reading.cs create mode 100644 AirAware/ViewModels/CreateReadingViewModel.cs diff --git a/AirAware/Controllers/ReadingController.cs b/AirAware/Controllers/ReadingController.cs new file mode 100644 index 0000000..4fe07c7 --- /dev/null +++ b/AirAware/Controllers/ReadingController.cs @@ -0,0 +1,69 @@ +using AirAware.Data; +using AirAware.Models; +using AirAware.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace AirAware.Controllers; + +[ApiController] +[Route("api/v1")] +public class ReadingController: ControllerBase +{ + [HttpGet] + [Route("readings")] + public async Task GetAsync([FromServices] AppDbContext context) + { + var readings = await context + .Readings + .AsNoTracking() + .ToListAsync(); + return Ok(readings); + } + + [HttpGet] + [Route("readings/{id}")] + public async Task GetByIdAsync( + [FromServices] AppDbContext context, + [FromRoute] Guid id + ) + { + var reading = await context + .Readings + .AsNoTracking() + .FirstOrDefaultAsync(r => r.Id == id); + + return reading == null + ? NotFound() + : Ok(reading); + } + + [HttpPost("readings")] + public async Task PostAsync( + [FromServices] AppDbContext context, + [FromBody] CreateReadingViewModel model + ) + { + if (!ModelState.IsValid) + return BadRequest(); + + var reading = new Reading + { + StationId = model.StationId, + Pm2_5 = model.Pm2_5, + Pm10 = model.Pm10, + RawPayload = model.RawPayload + }; + + try + { + await context.Readings.AddAsync(reading); + await context.SaveChangesAsync(); + return Created($"v1/readings/{reading.Id}", reading); + } + catch (Exception) + { + return StatusCode(StatusCodes.Status500InternalServerError); + } + } +} \ No newline at end of file diff --git a/AirAware/Data/AppDbContext.cs b/AirAware/Data/AppDbContext.cs index c8741f8..b10af74 100644 --- a/AirAware/Data/AppDbContext.cs +++ b/AirAware/Data/AppDbContext.cs @@ -6,6 +6,7 @@ namespace AirAware.Data; public class AppDbContext: DbContext { public DbSet Stations { get; set; } + public DbSet Readings { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlite("DataSource=app.db;Cache=Shared"); diff --git a/AirAware/Models/Reading.cs b/AirAware/Models/Reading.cs new file mode 100644 index 0000000..df903fd --- /dev/null +++ b/AirAware/Models/Reading.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace AirAware.Models; + +public class Reading +{ + public Guid Id { get; set; } = Guid.NewGuid(); + public Guid StationId { get; set; } + [JsonIgnore] + public Station Station { get; set; } = null!; + public double Pm2_5 { get; set; } + public double Pm10 { get; set; } + public string? RawPayload { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.Now; +} \ No newline at end of file diff --git a/AirAware/ViewModels/CreateReadingViewModel.cs b/AirAware/ViewModels/CreateReadingViewModel.cs new file mode 100644 index 0000000..c6e33a1 --- /dev/null +++ b/AirAware/ViewModels/CreateReadingViewModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace AirAware.ViewModels; + +public class CreateReadingViewModel +{ + [Required] + public Guid StationId { get; set; } + [Required] + public double Pm2_5 { get; set; } + [Required] + public double Pm10 { get; set; } + public string? RawPayload { get; set; } +} \ No newline at end of file From 4c5a79f32569764cbd2182b9cc32a8e592131629 Mon Sep 17 00:00:00 2001 From: Joao Ferreira Date: Sun, 8 Feb 2026 12:13:12 -0300 Subject: [PATCH 2/3] fix: adjuting POST method Created route --- AirAware/Controllers/ReadingController.cs | 2 +- AirAware/Controllers/StationController.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AirAware/Controllers/ReadingController.cs b/AirAware/Controllers/ReadingController.cs index 4fe07c7..2b81328 100644 --- a/AirAware/Controllers/ReadingController.cs +++ b/AirAware/Controllers/ReadingController.cs @@ -59,7 +59,7 @@ [FromBody] CreateReadingViewModel model { await context.Readings.AddAsync(reading); await context.SaveChangesAsync(); - return Created($"v1/readings/{reading.Id}", reading); + return Created($"api/v1/readings/{reading.Id}", reading); } catch (Exception) { diff --git a/AirAware/Controllers/StationController.cs b/AirAware/Controllers/StationController.cs index 9705e5d..1128703 100644 --- a/AirAware/Controllers/StationController.cs +++ b/AirAware/Controllers/StationController.cs @@ -60,7 +60,7 @@ [FromBody] CreateStationViewModel model { await context.Stations.AddAsync(station); await context.SaveChangesAsync(); - return Created($"v1/stations/{station.Id}", station); + return Created($"api/v1/stations/{station.Id}", station); } catch (Exception) { From f07820d2683d9458af61cfebd67636ff1b5df82c Mon Sep 17 00:00:00 2001 From: Joao Ferreira Date: Sun, 8 Feb 2026 12:22:48 -0300 Subject: [PATCH 3/3] chore: validating if station exists --- AirAware/Controllers/ReadingController.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/AirAware/Controllers/ReadingController.cs b/AirAware/Controllers/ReadingController.cs index 2b81328..cd3b2ec 100644 --- a/AirAware/Controllers/ReadingController.cs +++ b/AirAware/Controllers/ReadingController.cs @@ -45,7 +45,15 @@ [FromBody] CreateReadingViewModel model ) { if (!ModelState.IsValid) - return BadRequest(); + return BadRequest("Invalid data provided."); + + var station = await context + .Stations + .AsNoTracking() + .FirstOrDefaultAsync(s => s.Id == model.StationId); + + if (station == null) + return BadRequest("Station with the provided ID does not exist."); var reading = new Reading {