Skip to content

Commit

Permalink
add API with CreateCar POST request
Browse files Browse the repository at this point in the history
  • Loading branch information
stephen1426 committed Jan 7, 2025
1 parent 587453c commit 5d8cabf
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/AcGarageApp/AcGarageAPI/AcGarageAPI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Adapters/MapCarDtoToCarAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using AcGarageAPI.DtoModels;
using AcGarageAPI.Entities;

namespace AcGarageAPI.Adapters;

public static class MapCarDtoToCarAdapter
{
public static Car ToCar(this CarDto carDto)
{
return new Car
{
Make = carDto.Make,
Model = carDto.Model,
Registration = carDto.Registration,
Price = carDto.Price!.Value
};
}
}
23 changes: 23 additions & 0 deletions src/AcGarageApp/AcGarageAPI/CQS/Commands/CreateCar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using AcGarageAPI.Adapters;
using AcGarageAPI.Data;
using AcGarageAPI.DtoModels;
using MediatR;

namespace AcGarageAPI.CQS.Commands;

public class CreateCar(CarDto carDto) : IRequest
{
public CarDto CarDto { get; set; } = carDto;
}

public class CreateCarHandler(GarageDbContext context) : IRequestHandler<CreateCar>
{
public async Task Handle(CreateCar request, CancellationToken cancellationToken)
{
var car = request.CarDto.ToCar();

await context.Cars.AddAsync(car, cancellationToken);

await context.SaveChangesAsync(cancellationToken);
}
}
20 changes: 20 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Controllers/CarController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using AcGarageAPI.CQS.Commands;
using AcGarageAPI.DtoModels;
using MediatR;
using Microsoft.AspNetCore.Mvc;

namespace AcGarageAPI.Controllers;

[ApiController]
[Route("api/[controller]")]
public class CarController(IMediator mediator) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> PostCar([FromBody, Required] CarDto input)
{
await mediator.Send(new CreateCar(input));

return Ok();
}
}
32 changes: 32 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Data/GarageDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using AcGarageAPI.Entities;
using Microsoft.EntityFrameworkCore;

namespace AcGarageAPI.Data;

public class GarageDbContext(DbContextOptions options) : DbContext(options)
{
public DbSet<Car> Cars { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>().Property(e => e.Make)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);

modelBuilder.Entity<Car>().Property(e => e.Model)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);

modelBuilder.Entity<Car>().Property(e => e.Registration)
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false);

modelBuilder.Entity<Car>()
.ToTable(nameof(Car));

base.OnModelCreating(modelBuilder);
}
}
18 changes: 18 additions & 0 deletions src/AcGarageApp/AcGarageAPI/DtoModels/CarDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;

namespace AcGarageAPI.DtoModels;

public class CarDto
{
[Required, StringLength(100, MinimumLength = 1)]
public string Make { get; set; }

[Required, StringLength(100, MinimumLength = 1)]
public string Model { get; set; }

[Required, StringLength(10, MinimumLength = 1)]
public string Registration { get; set; }

[Required]
public decimal? Price { get; set; }
}
10 changes: 10 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Entities/Car.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AcGarageAPI.Entities;

public class Car
{
public Guid Id { get; set; }
public required string Make { get; set; }
public required string Model { get; set; }
public required string Registration { get; set; }
public required decimal Price { get; set; }
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace AC.Garage.Migrations
{
/// <inheritdoc />
public partial class AddCarEntity : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Car",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Make = table.Column<string>(type: "varchar(100)", unicode: false, maxLength: 100, nullable: false),
Model = table.Column<string>(type: "varchar(100)", unicode: false, maxLength: 100, nullable: false),
Registration = table.Column<string>(type: "varchar(10)", unicode: false, maxLength: 10, nullable: false),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Car", x => x.Id);
});
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Car");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// <auto-generated />
using System;
using AcGarageAPI.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

#nullable disable

namespace AC.Garage.Migrations
{
[DbContext(typeof(GarageDbContext))]
partial class GarageDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 128);

SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);

modelBuilder.Entity("AC.Garage.Entities.Car", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");

b.Property<string>("Make")
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false)
.HasColumnType("varchar(100)");

b.Property<string>("Model")
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false)
.HasColumnType("varchar(100)");

b.Property<decimal>("Price")
.HasColumnType("decimal(18,2)");

b.Property<string>("Registration")
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false)
.HasColumnType("varchar(10)");

b.HasKey("Id");

b.ToTable("Car", (string)null);
});
#pragma warning restore 612, 618
}
}
}
41 changes: 41 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using AcGarageAPI.Data;
using Microsoft.EntityFrameworkCore;

namespace AcGarageAPI;

public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddDbContext<GarageDbContext>(opts =>
opts.UseSqlServer(builder.Configuration.GetConnectionString(nameof(GarageDbContext))));

builder.Services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
}
}
15 changes: 15 additions & 0 deletions src/AcGarageApp/AcGarageAPI/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7294;http://localhost:5054",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
8 changes: 8 additions & 0 deletions src/AcGarageApp/AcGarageAPI/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Loading

0 comments on commit 5d8cabf

Please sign in to comment.