mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Restructure data access layer/data layer
This commit is contained in:
@@ -9,7 +9,7 @@ namespace DALTests
|
||||
{
|
||||
public class UserAccountRepositoryTests
|
||||
{
|
||||
private readonly UserAccountRepository _repository;
|
||||
private readonly IUserAccountRepository _repository;
|
||||
|
||||
public UserAccountRepositoryTests()
|
||||
{
|
||||
|
||||
13
DataAccessLayer/Repositories/IUserAccountRepository.cs
Normal file
13
DataAccessLayer/Repositories/IUserAccountRepository.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DataAccessLayer.Entities;
|
||||
|
||||
namespace DataAccessLayer
|
||||
{
|
||||
public interface IUserAccountRepository : IRepository<UserAccount>
|
||||
{
|
||||
IEnumerable<UserAccount> GetAll();
|
||||
UserAccount? GetByUsername(string username);
|
||||
UserAccount? GetByEmail(string email);
|
||||
}
|
||||
}
|
||||
163
DataAccessLayer/Repositories/UserAccountRepository.cs
Normal file
163
DataAccessLayer/Repositories/UserAccountRepository.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DataAccessLayer.Entities;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace DataAccessLayer
|
||||
{
|
||||
public class UserAccountRepository : IUserAccountRepository
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
public UserAccountRepository()
|
||||
{
|
||||
// Retrieve the connection string from environment variables
|
||||
_connectionString =
|
||||
Environment.GetEnvironmentVariable("DB_CONNECTION_STRING")
|
||||
?? throw new InvalidOperationException(
|
||||
"The connection string is not set in the environment variables."
|
||||
);
|
||||
}
|
||||
|
||||
public void Add(UserAccount userAccount)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new("usp_CreateUserAccount", connection);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
AddUserAccountCreateParameters(command, userAccount);
|
||||
connection.Open();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public UserAccount? GetById(Guid id)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new(
|
||||
"usp_GetUserAccountById",
|
||||
connection
|
||||
);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
command.Parameters.AddWithValue("@UserAccountId", id);
|
||||
connection.Open();
|
||||
|
||||
using SqlDataReader reader = command.ExecuteReader();
|
||||
return reader.Read() ? MapUserAccount(reader) : null;
|
||||
}
|
||||
|
||||
public void Update(UserAccount userAccount)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new("usp_UpdateUserAccount", connection);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
AddUserAccountUpdateParameters(command, userAccount);
|
||||
connection.Open();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public void Delete(Guid id)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new(
|
||||
"usp_DeleteUserAccount",
|
||||
connection
|
||||
);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
command.Parameters.AddWithValue("@UserAccountId", id);
|
||||
connection.Open();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public IEnumerable<UserAccount> GetAll()
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new(
|
||||
"usp_GetAllUserAccounts",
|
||||
connection
|
||||
);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
connection.Open();
|
||||
|
||||
using SqlDataReader reader = command.ExecuteReader();
|
||||
List<UserAccount> users = new();
|
||||
while (reader.Read())
|
||||
{
|
||||
users.Add(MapUserAccount(reader));
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public UserAccount? GetByUsername(string username)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new(
|
||||
"usp_GetUserAccountByUsername",
|
||||
connection
|
||||
);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
command.Parameters.AddWithValue("@Username", username);
|
||||
connection.Open();
|
||||
|
||||
using SqlDataReader reader = command.ExecuteReader();
|
||||
return reader.Read() ? MapUserAccount(reader) : null;
|
||||
}
|
||||
|
||||
public UserAccount? GetByEmail(string email)
|
||||
{
|
||||
using SqlConnection connection = new(_connectionString);
|
||||
using SqlCommand command = new(
|
||||
"usp_GetUserAccountByEmail",
|
||||
connection
|
||||
);
|
||||
command.CommandType = System.Data.CommandType.StoredProcedure;
|
||||
command.Parameters.AddWithValue("@Email", email);
|
||||
connection.Open();
|
||||
|
||||
using SqlDataReader reader = command.ExecuteReader();
|
||||
return reader.Read() ? MapUserAccount(reader) : null;
|
||||
}
|
||||
|
||||
private static void AddUserAccountCreateParameters(
|
||||
SqlCommand command,
|
||||
UserAccount userAccount
|
||||
)
|
||||
{
|
||||
command.Parameters.AddWithValue(
|
||||
"@UserAccountId",
|
||||
userAccount.UserAccountID
|
||||
);
|
||||
command.Parameters.AddWithValue("@Username", userAccount.Username);
|
||||
command.Parameters.AddWithValue("@FirstName", userAccount.FirstName);
|
||||
command.Parameters.AddWithValue("@LastName", userAccount.LastName);
|
||||
command.Parameters.AddWithValue("@Email", userAccount.Email);
|
||||
command.Parameters.AddWithValue("@DateOfBirth", userAccount.DateOfBirth);
|
||||
}
|
||||
|
||||
private static void AddUserAccountUpdateParameters(
|
||||
SqlCommand command,
|
||||
UserAccount userAccount
|
||||
)
|
||||
{
|
||||
AddUserAccountCreateParameters(command, userAccount);
|
||||
command.Parameters.AddWithValue(
|
||||
"@UserAccountId",
|
||||
userAccount.UserAccountID
|
||||
);
|
||||
}
|
||||
|
||||
private static UserAccount MapUserAccount(SqlDataReader reader)
|
||||
{
|
||||
return new UserAccount
|
||||
{
|
||||
UserAccountID = reader.GetGuid(0),
|
||||
Username = reader.GetString(1),
|
||||
FirstName = reader.GetString(2),
|
||||
LastName = reader.GetString(3),
|
||||
Email = reader.GetString(4),
|
||||
CreatedAt = reader.GetDateTime(5),
|
||||
UpdatedAt = reader.IsDBNull(6) ? null : reader.GetDateTime(6),
|
||||
DateOfBirth = reader.GetDateTime(7),
|
||||
Timer = reader.IsDBNull(8) ? null : (byte[])reader[8],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Data;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace DataAccessLayer
|
||||
namespace DataAccessLayer.Sql
|
||||
{
|
||||
public class DatabaseHelper
|
||||
{
|
||||
@@ -3,6 +3,7 @@ GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_CreateUserAccount
|
||||
(
|
||||
@UserAccountId UNIQUEIDENTIFIER = NULL,
|
||||
@Username VARCHAR(64),
|
||||
@FirstName NVARCHAR(128),
|
||||
@LastName NVARCHAR(128),
|
||||
@@ -17,6 +18,7 @@ BEGIN
|
||||
|
||||
INSERT INTO UserAccount
|
||||
(
|
||||
UserAccountID,
|
||||
Username,
|
||||
FirstName,
|
||||
LastName,
|
||||
@@ -25,6 +27,7 @@ BEGIN
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
COALESCE(@UserAccountId, NEWID()),
|
||||
@Username,
|
||||
@FirstName,
|
||||
@LastName,
|
||||
@@ -40,7 +43,7 @@ GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_DeleteUserAccount
|
||||
(
|
||||
@UserAccountId INT
|
||||
@UserAccountId UNIQUEIDENTIFIER
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
@@ -70,7 +73,7 @@ CREATE OR ALTER PROCEDURE usp_UpdateUserAccount
|
||||
@LastName NVARCHAR(128),
|
||||
@DateOfBirth DATETIME,
|
||||
@Email VARCHAR(128),
|
||||
@UserAccountId GUID
|
||||
@UserAccountId UNIQUEIDENTIFIER
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
@@ -98,3 +101,87 @@ BEGIN
|
||||
COMMIT TRANSACTION
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_GetUserAccountById
|
||||
(
|
||||
@UserAccountId UNIQUEIDENTIFIER
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT UserAccountID,
|
||||
Username,
|
||||
FirstName,
|
||||
LastName,
|
||||
Email,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
DateOfBirth,
|
||||
Timer
|
||||
FROM dbo.UserAccount
|
||||
WHERE UserAccountID = @UserAccountId;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_GetAllUserAccounts
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT UserAccountID,
|
||||
Username,
|
||||
FirstName,
|
||||
LastName,
|
||||
Email,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
DateOfBirth,
|
||||
Timer
|
||||
FROM dbo.UserAccount;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_GetUserAccountByUsername
|
||||
(
|
||||
@Username VARCHAR(64)
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT UserAccountID,
|
||||
Username,
|
||||
FirstName,
|
||||
LastName,
|
||||
Email,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
DateOfBirth,
|
||||
Timer
|
||||
FROM dbo.UserAccount
|
||||
WHERE Username = @Username;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE usp_GetUserAccountByEmail
|
||||
(
|
||||
@Email VARCHAR(128)
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT UserAccountID,
|
||||
Username,
|
||||
FirstName,
|
||||
LastName,
|
||||
Email,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
DateOfBirth,
|
||||
Timer
|
||||
FROM dbo.UserAccount
|
||||
WHERE Email = @Email;
|
||||
END;
|
||||
GO
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using DataAccessLayer.Entities;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace DataAccessLayer
|
||||
{
|
||||
public class UserAccountRepository : IRepository<UserAccount>
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public UserAccountRepository()
|
||||
{
|
||||
// Retrieve the connection string from environment variables
|
||||
_connectionString =
|
||||
Environment.GetEnvironmentVariable("DB_CONNECTION_STRING")
|
||||
?? throw new InvalidOperationException(
|
||||
"The connection string is not set in the environment variables."
|
||||
);
|
||||
}
|
||||
|
||||
public void Add(UserAccount userAccount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UserAccount? GetById(Guid id)
|
||||
{
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Update(UserAccount userAccount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Delete(Guid id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<UserAccount> GetAll()
|
||||
{
|
||||
return new List<UserAccount>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
51
README.md
Normal file
51
README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Biergarten SQL Server - Architecture Overview
|
||||
|
||||
This solution is a monolith-oriented Web API with a layered structure. The current focus is a SQL Server-backed data layer with stored procedures and a repository-based DAL.
|
||||
|
||||
## High-level projects
|
||||
|
||||
- `WebAPI/` - ASP.NET Core API endpoints (controllers) and application entrypoint.
|
||||
- `BusinessLayer/` - Intended home for domain/business logic (currently minimal).
|
||||
- `DataAccessLayer/` - Repository implementations, entities (POCOs), and SQL helpers.
|
||||
- `DataLayer/` - Database schema, seed scripts, and data sources.
|
||||
- `WebCrawler/` - Separate crawler executable.
|
||||
- `DALTests/` - Data access tests.
|
||||
|
||||
## Data access architecture
|
||||
|
||||
- **Entities (POCOs)** live in `DataAccessLayer/Entities/`.
|
||||
- **Repositories** live in `DataAccessLayer/Repositories/` and implement interfaces like `IUserAccountRepository`.
|
||||
- **SQL execution** lives in `DataAccessLayer/Sql/`.
|
||||
- **Stored procedures** for CRUD live under `DataAccessLayer/Sql/crud/` and are invoked by repositories.
|
||||
|
||||
Example flow:
|
||||
|
||||
```
|
||||
WebAPI Controller -> IUserAccountRepository -> UserAccountRepository -> stored procedure
|
||||
```
|
||||
|
||||
The repositories are currently responsible for:
|
||||
- Opening connections using `DB_CONNECTION_STRING`
|
||||
- Executing stored procedures
|
||||
- Mapping result sets to POCOs
|
||||
|
||||
## Database schema and seed
|
||||
|
||||
- `DataLayer/schema.sql` contains the database schema definitions.
|
||||
- `DataLayer/seed/SeedDB.cs` provides seeding and stored procedure/function loading.
|
||||
- Stored procedure scripts are organized under `DataAccessLayer/Sql/crud/` (UserAccount and related).
|
||||
|
||||
## Key conventions
|
||||
|
||||
- **Environment variables**: `DB_CONNECTION_STRING` is required for DAL and seed tooling.
|
||||
- **Stored procedures**: CRUD operations use `usp_*` procedures.
|
||||
- **Rowversion** columns are represented as `byte[]` in entities (e.g., `Timer`).
|
||||
|
||||
## Suggested dependency direction
|
||||
|
||||
```
|
||||
WebAPI -> BusinessLayer -> DataAccessLayer -> SQL Server
|
||||
-> DataLayer (schema/seed/scripts)
|
||||
```
|
||||
|
||||
Keep business logic in `BusinessLayer` and avoid direct SQL or ADO code outside `DataAccessLayer`.
|
||||
@@ -1,75 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebAPI.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/beers")]
|
||||
public class BeersController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult GetBeers([FromQuery] int page_num, [FromQuery] int page_size)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("search")]
|
||||
public IActionResult SearchBeers([FromQuery] string search)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("styles")]
|
||||
public IActionResult GetBeerStyles([FromQuery] int page_num, [FromQuery] int page_size)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("styles/create")]
|
||||
public IActionResult CreateBeerStyle([FromBody] BeerStyleCreateRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPut("{postId}")]
|
||||
public IActionResult EditBeer(string postId, [FromBody] BeerEditRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("{postId}")]
|
||||
public IActionResult DeleteBeer(string postId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("{postId}/recommendations")]
|
||||
public IActionResult GetBeerRecommendations([FromQuery] int page_num, [FromQuery] int page_size, string postId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("{postId}/comments")]
|
||||
public IActionResult AddBeerComment(string postId, [FromBody] BeerCommentRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("{postId}/comments")]
|
||||
public IActionResult GetBeerComments([FromQuery] int page_num, [FromQuery] int page_size, string postId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPut("{postId}/comments/{commentId}")]
|
||||
public IActionResult EditBeerComment(string postId, string commentId, [FromBody] BeerCommentRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("{postId}/comments/{commentId}")]
|
||||
public IActionResult DeleteBeerComment(string postId, string commentId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebAPI.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/breweries")]
|
||||
public class BreweriesController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult GetBreweries([FromQuery] int page_num, [FromQuery] int page_size)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("map")]
|
||||
public IActionResult GetBreweriesMap([FromQuery] int page_num, [FromQuery] int page_size)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPut("{postId}")]
|
||||
public IActionResult EditBrewery(string postId, [FromBody] BreweryEditRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("{postId}")]
|
||||
public IActionResult DeleteBrewery(string postId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost("{postId}/comments")]
|
||||
public IActionResult AddBreweryComment(string postId, [FromBody] BreweryCommentRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("{postId}/comments")]
|
||||
public IActionResult GetBreweryComments([FromQuery] int page_num, [FromQuery] int page_size, string postId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPut("{postId}/comments/{commentId}")]
|
||||
public IActionResult EditBreweryComment(string postId, string commentId, [FromBody] BreweryCommentRequest request)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("{postId}/comments/{commentId}")]
|
||||
public IActionResult DeleteBreweryComment(string postId, string commentId)
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using DataAccessLayer;
|
||||
using DataAccessLayer.Entities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebAPI.Controllers
|
||||
{
|
||||
@@ -7,7 +8,7 @@ namespace WebAPI.Controllers
|
||||
[Route("api/users")]
|
||||
public class UsersController : ControllerBase
|
||||
{
|
||||
private readonly UserAccountRepository _userAccountRepository;
|
||||
private readonly IUserAccountRepository _userAccountRepository;
|
||||
|
||||
public UsersController()
|
||||
{
|
||||
@@ -15,6 +16,7 @@ namespace WebAPI.Controllers
|
||||
}
|
||||
|
||||
// all users
|
||||
[HttpGet]
|
||||
[HttpGet("users")]
|
||||
public IActionResult GetAllUsers()
|
||||
{
|
||||
@@ -22,5 +24,61 @@ namespace WebAPI.Controllers
|
||||
return Ok(users);
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public IActionResult GetUserById(Guid id)
|
||||
{
|
||||
var user = _userAccountRepository.GetById(id);
|
||||
return user is null ? NotFound() : Ok(user);
|
||||
}
|
||||
|
||||
[HttpGet("by-username/{username}")]
|
||||
public IActionResult GetUserByUsername(string username)
|
||||
{
|
||||
var user = _userAccountRepository.GetByUsername(username);
|
||||
return user is null ? NotFound() : Ok(user);
|
||||
}
|
||||
|
||||
[HttpGet("by-email/{email}")]
|
||||
public IActionResult GetUserByEmail(string email)
|
||||
{
|
||||
var user = _userAccountRepository.GetByEmail(email);
|
||||
return user is null ? NotFound() : Ok(user);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult CreateUser([FromBody] UserAccount userAccount)
|
||||
{
|
||||
if (userAccount.UserAccountID == Guid.Empty)
|
||||
{
|
||||
userAccount.UserAccountID = Guid.NewGuid();
|
||||
}
|
||||
|
||||
_userAccountRepository.Add(userAccount);
|
||||
return CreatedAtAction(
|
||||
nameof(GetUserById),
|
||||
new { id = userAccount.UserAccountID },
|
||||
userAccount
|
||||
);
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
public IActionResult UpdateUser(Guid id, [FromBody] UserAccount userAccount)
|
||||
{
|
||||
if (userAccount.UserAccountID != Guid.Empty && userAccount.UserAccountID != id)
|
||||
{
|
||||
return BadRequest("UserAccountID does not match route id.");
|
||||
}
|
||||
|
||||
userAccount.UserAccountID = id;
|
||||
_userAccountRepository.Update(userAccount);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public IActionResult DeleteUser(Guid id)
|
||||
{
|
||||
_userAccountRepository.Delete(id);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,9 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
var app = builder.Build();
|
||||
@@ -39,6 +42,8 @@ var app = builder.Build();
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.MapOpenApi();
|
||||
}
|
||||
|
||||
@@ -58,24 +63,6 @@ var summaries = new[]
|
||||
"Scorching",
|
||||
};
|
||||
|
||||
app.MapGet(
|
||||
"/weatherforecast",
|
||||
() =>
|
||||
{
|
||||
var forecast = Enumerable
|
||||
.Range(1, 5)
|
||||
.Select(index => new WeatherForecast(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
summaries[Random.Shared.Next(summaries.Length)]
|
||||
))
|
||||
.ToArray();
|
||||
return forecast;
|
||||
}
|
||||
)
|
||||
.WithName("GetWeatherForecast");
|
||||
|
||||
// Register controllers
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,3 +4,61 @@ GET {{WebAPI_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
|
||||
GET {{WebAPI_HostAddress}}/api/users
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
|
||||
GET {{WebAPI_HostAddress}}/api/users/{{userId}}
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
|
||||
GET {{WebAPI_HostAddress}}/api/users/by-username/{{username}}
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
|
||||
GET {{WebAPI_HostAddress}}/api/users/by-email/{{email}}
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
|
||||
POST {{WebAPI_HostAddress}}/api/users
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
|
||||
{
|
||||
"userAccountID": "00000000-0000-0000-0000-000000000000",
|
||||
"username": "testuser",
|
||||
"firstName": "Test",
|
||||
"lastName": "User",
|
||||
"email": "testuser@example.com",
|
||||
"createdAt": "2025-01-01T00:00:00Z",
|
||||
"updatedAt": null,
|
||||
"dateOfBirth": "1990-01-01T00:00:00Z",
|
||||
"timer": null
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
PUT {{WebAPI_HostAddress}}/api/users/{{userId}}
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
|
||||
{
|
||||
"userAccountID": "{{userId}}",
|
||||
"username": "testuser",
|
||||
"firstName": "Updated",
|
||||
"lastName": "User",
|
||||
"email": "testuser@example.com",
|
||||
"createdAt": "2025-01-01T00:00:00Z",
|
||||
"updatedAt": "2025-02-01T00:00:00Z",
|
||||
"dateOfBirth": "1990-01-01T00:00:00Z",
|
||||
"timer": null
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
DELETE {{WebAPI_HostAddress}}/api/users/{{userId}}
|
||||
|
||||
@@ -17,40 +17,6 @@ services:
|
||||
retries: 12
|
||||
networks:
|
||||
- devnet
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
container_name: redis
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- devnet
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
dotnet:
|
||||
image: mcr.microsoft.com/dotnet/sdk:10.0
|
||||
container_name: dotnet-sdk
|
||||
tty: true
|
||||
stdin_open: true
|
||||
volumes:
|
||||
- ./:/home/dev/projects
|
||||
- nuget-cache:/home/dev/.nuget/packages
|
||||
- ~/.gitconfig:/home/dev/.gitconfig:ro
|
||||
working_dir: /home/dev/projects
|
||||
environment:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
|
||||
HOME: /home/dev
|
||||
USER: dev
|
||||
DB_CONNECTION_STRING: "Server=sqlserver,1433;User Id=sa;Password=${SA_PASSWORD};Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;Database=${DB_NAME};"
|
||||
REDIS_URL: "${REDIS_URL}"
|
||||
user: root
|
||||
networks:
|
||||
- devnet
|
||||
|
||||
volumes:
|
||||
sqlserverdata:
|
||||
nuget-cache:
|
||||
|
||||
Reference in New Issue
Block a user