Marktguru-Api is a C# project that provides an API for managing products. It includes features such as product creation, validation, and logging.
This project uses a InMemoryDatabase – this is of course not suitable for production purposes. For the simplicity of the project, Authentication is done using a hardcoded username and password and is included as endpoint inside the project. The access layer uses Entity Framework Core. The API is built using ASP.NET Core and MediatR.
Swagger documentation can be found under /swagger/index.html. First login under the /token endpoint, copy the token from the response and authorize the swagger documentation with the token.
Clone the repository:
git clone https://github.com/yourusername/MarktguruApi.git
Navigate to the project directory:
cd /src/MarktguruApi
Restore the dependencies:
dotnet restore
Build the project:
dotnet build
Run the project:
dotnet run
You can also build and run the project using Docker.
Navigate to the project directory:
cd /src
Build the Docker image:
docker build -t marktguruapi -f MarktguruApi/Dockerfile .
Run the Docker container:
docker run -p 5000:8080 marktguruapi
- src/MarktguruApi/: Contains the main source code for the API.
- Controllers/: Contains the API controllers.
- Models/: Contains the data models.
- Validation/: Contains the validation logic.
- Behaviors/: Contains the MediatR pipeline behaviors.
- Utils/: Contains utility classes and global exception handling.
- MediatR/: Contains the MediatR query, command and handler classes.
- Repositories/: Contains the repository classes.
- tests/MarktguruApiTests/: Contains unit tests for the API.
Authentication is required to access parts of the API.
To authenticate, you can use the following credentials:
- Username: Test
- Password: test
You can use the following endpoint to authenticate:
- POST /token: Authenticate a user.
There are several endpoints available for managing products:
- GET /api/products: Get all products.
- GET /api/products/{id}: Get a product by ID.
- POST /api/products: Create a new product.
- PUT /api/products/{id}: Update a product by ID.
- DELETE /api/products/{id}: Delete a product by ID.
- GET /api/products/paginated: Get paginated products.
Additionally, there is an endpoint for health checks:
- GET /health: Check the health of the API.
You can find a Postman collection within the docs folder.
The update endpoint checks if an entry with the same version is available. It raises a conflict if the version differs. Because of limitation of the InMemoryDatabase, the version is not generated by the database itself but inside the code.
The GET endpoints are using a simple ResponseCache to reduce the load on the server. In a production environment, the responses should be cached using a distributed cache like Redis. Additionally, in a production environment, the instances of the service should be scaled horizontally with a load balancer.
The Assignment asked for an endpoint that returns all the products. This will cause problems as soon as the number of products grows. To counter this, the project includes a paginated endpoint.
The project is optimized for read operations. The write operations aren't optimized. I assumed that the read operations are more frequent than the write operations. To optimize write operations, the project should subscribe to a message queue like RabbitMQ or Kafka. This would allow the project to handle write operations asynchronously. If the use of RabbitMQ or Kafka is not suitable, the project should use rate limiting to keep the system stable.
The project writes the logs to the console. In a production environment, the logs should be written to a log management system like AWS CloudWatch or Azure Monitor.
The project includes a health check endpoint. In a production environment, the health checks should be monitored using a monitoring system like Grafana. In addition, the project should also return a health status of connected services like databases.
The project uses a hardcoded username, password and secret for authentication. This is not secure and should be replaced with injecting the secret from the environment variables or from a secure store.
The password is currently stored in plain text in the source code. In a production environment, the password should be hashed and salted.
Instead of hard delete, the project may use a soft delete. This would allow the project to keep the data for auditing purposes. Also, maybe not every user should be able to delete a product. This should be handled by roles and permissions.
For a better understanding of the transactions in the database, an audit log should be implemented.
For the simplicity of the project, transactions aren't used. But it is recommended to use transactions to ensure data consistency.
The project includes unit tests for the API. To get a better understanding of the performance of the API stress-tests, load-tests should be performed and monitored. Tools for this are, for example, k6.
The project does not include Behavior-Driven Development (BDD) tests. I would recommend using BDD test to ensure that the project meets the requirements of the stakeholders.
Code reviews are an important part of the development process. Perhaps also consider static code analysis tools, for example, something like Sonarqube or Qodana, for code quality assurance and to identify risks in the code base.