Skip to content

Commit 7f30cc4

Browse files
authored
Update README.md
1 parent 178cdec commit 7f30cc4

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

README.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,190 @@
11
# TasksAPI
2+
3+
Base template project for development with ASP.NET server using DDD and Clean Architecture principles.
4+
5+
The project contains some base entities to simulate tasks, categories and users.
6+
7+
You may need configure *appsettings.json* to get it to work.
8+
9+
## Features
10+
11+
* Entity framework ORM (tested with SQL Server)
12+
* DDD based implementation
13+
* Unit and Integration Tests
14+
* CQRS pattern for use cases
15+
* Auto logging with independent transaction
16+
* Migrations
17+
* Result pattern, avoiding throws
18+
* Api fixed base response
19+
20+
# Layers
21+
22+
The project has a layered structure as follows.
23+
24+
![image](https://github.com/user-attachments/assets/64e72fce-3414-4816-8668-91877f938ba4)
25+
26+
## API (Presentation)
27+
28+
This layer is responsible for the presentation of the application, defining endpoints (controllers) and responses.
29+
30+
This layer typically receives data from the front-end and calls a mediator through the CQRS pattern, which then invokes the application layer.
31+
32+
It should also handle how the response data should be presented.
33+
34+
```C#
35+
/// <summary>
36+
/// Create a new category
37+
/// </summary>
38+
[Authorize]
39+
[HttpPost]
40+
[SwaggerResponse(StatusCodes.Status200OK, Type = typeof(BaseResponse))]
41+
[SwaggerResponse(StatusCodes.Status400BadRequest, Type = typeof(BaseResponse))]
42+
[SwaggerResponse(StatusCodes.Status500InternalServerError, Type = typeof(BaseResponse))]
43+
public async Task<IActionResult> CreateCategory([FromBody] CreateCategoryCommand command)
44+
{
45+
return await HandleApplicationResponse<Operation>(
46+
command,
47+
(resp) =>
48+
{
49+
return new()
50+
{
51+
Success = resp.Success,
52+
Response = null,
53+
ErrorMessage = resp.Message,
54+
Code = resp.Success ? 200 : 400
55+
};
56+
}
57+
);
58+
}
59+
```
60+
61+
## Application (Use cases)
62+
63+
This layer coordinates the use cases, interacting with the domain layer, infrastructure layer, and presentation layer.
64+
65+
In our project, the CQRS pattern is used. In the code, you can see that the application layer is responsible for invoking the object creation, validating it, persisting it, and returning the result.
66+
67+
```C#
68+
public async Task<Operation> Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
69+
{
70+
if (request == null)
71+
return Operation.MakeFailure("Invalid request");
72+
73+
var createModel = _mapper.Map<CreateCategoryModel>(request);
74+
createModel.UserId = _tokenService.GetToken().Id;
75+
76+
var newCategoryResult = await _categoryBusiness.Create(createModel);
77+
78+
if(!newCategoryResult.Success)
79+
return Operation.MakeFailure(newCategoryResult.Message);
80+
81+
await _uow.Begin();
82+
83+
await _categoryRepo.Create(newCategoryResult.Content);
84+
85+
await _uow.Save();
86+
await _uow.Commit();
87+
88+
return Operation.MakeSuccess();
89+
}
90+
```
91+
92+
## Domain (Core)
93+
94+
This layer contains the business logic and is independent of all other layers. Here, we have the domain entities modeled with the business logic.
95+
96+
```C#
97+
/// <summary>
98+
/// Category entity
99+
/// </summary>
100+
public sealed class Category : BaseEntity
101+
{
102+
public string Name { get; private set; }
103+
public int UserId { get; private set; }
104+
105+
private Category() { }
106+
107+
private Category(string name, int userId)
108+
{
109+
Name = name;
110+
UserId = userId;
111+
}
112+
113+
public static Result<Category> Create(string name, int userId)
114+
{
115+
var result = ValidateAll(name, userId);
116+
117+
if (!result.Success)
118+
return Result.MakeFailure<Category>(result.Message);
119+
120+
var category = new Category(name, userId);
121+
122+
return Result.MakeSuccess(category);
123+
}
124+
...
125+
```
126+
127+
## Infraestructure
128+
129+
This layer is resposabile for data persistence and other services, usually will contain the code for the ORM and return domain entities.
130+
131+
In this layer we also have the persistence entities that are used by the ORM.
132+
133+
```C#
134+
/// <summary>
135+
/// Repository implementation for the Category entity
136+
/// </summary>
137+
public class CategoryRepository : Repository<DbCategory>, ICategoryRepository
138+
{
139+
public CategoryRepository(DatabaseContext ctx, IServiceProvider provider) : base(ctx.Categories, provider)
140+
{
141+
}
142+
143+
public async Task<bool> ExistsByName(string name, int? userId, int? currentId)
144+
{
145+
var filter = new Filter<DbCategory>(x => x.Name == name);
146+
147+
if(userId.HasValue && userId != default)
148+
filter.And(x => x.UserId == userId.Value);
149+
150+
if(currentId.HasValue && currentId != default)
151+
filter.And(x => x.Id != currentId.Value);
152+
153+
return await _dbSet.AnyAsync(filter.GetExpression());
154+
}
155+
...
156+
```
157+
158+
## IoC (Inversion of Control)
159+
160+
Responsible for the dependency injection (DI) and resolving dependencies of services.
161+
162+
# Swagger
163+
164+
Swagger is configured with basic documentation. It's possible to see the input data and the returning data according to the response code
165+
166+
![image](https://github.com/user-attachments/assets/3e375be0-16c4-41bc-aebc-df7e09d5c0e0)
167+
168+
# Tests
169+
170+
The project contains two test projects: unit tests and integration tests.
171+
172+
## Unit tests
173+
174+
Unit tests are performed in the domain layer, at the entity and domain service levels, using Moq to ensure there are no external dependencies.
175+
176+
### Entities
177+
![image](https://github.com/user-attachments/assets/0750163d-ceea-4ffa-8f0a-e45068f44737)
178+
### Domain services
179+
![image](https://github.com/user-attachments/assets/82a2db13-135f-4e17-b27f-afa4a1e6c37e)
180+
181+
## Integration tests
182+
183+
Integration tests are performed using a test SQL Server with fixed data at the infrastructure, application, and API levels
184+
### Infrastructure
185+
![image](https://github.com/user-attachments/assets/6b301d58-06d8-4dc4-b48e-c868f35b28ae)
186+
### Application
187+
![image](https://github.com/user-attachments/assets/85905bed-1c4a-42bc-ac3e-14336ad77269)
188+
### Api
189+
![image](https://github.com/user-attachments/assets/757237af-f4ae-42d5-9436-a0209b4c5e38)
190+

0 commit comments

Comments
 (0)