I've decided to use an onion architectural style for this API as I'm a big fan of it and feel it lends itself well to code reuse. The project structure is as follows:
- Domain: Contains domain entities and their related logic.
- Api: ASP.NET WebAPI stuff. (The application layer).
- Entities: Entity Framework Repositories. (I would have called it repositories if it didn't sound so similar to the parent solution).
- Api.Client: C# client libraries for communicating with the API.
- Api.Models: Model classes used by both the API and client library.
- Api.Tests: Unit tests for controllers.
- I chose to back my repositories with
SQLitebecause I developed this on linux and I don't have SQL Server set up. It should be painless to change though. - I decided to use
Seriloginstead ofMicrosoft.Extensions.Loggingbecause it has more features such as destructuring. I also chose not to DI my loggers because from my experience logging console output in tests can be useful. - I applied some simple domain-oriented interfaces such as `INamed" so in future I can write extension methods for any entity or collections of entities that have that interface.
- To seed the initial list of countries I used a library I wrote and published at my last role:
Audacia.Locality. - Tests are written using xUnit and FluentAssertions, and follow the structure described in this blog post by Phil Haack.
- To maintain a historical record of recipes, each update is saved as a new recipe, with a reference to the recipe it is based on.
- Entities with the
IAuditableinterface automatically have their CreatedDate set when saving (the DbContext handles this). - I generated the documentation with Swagger. Its my first time using it actually, i followed this guide
- I considered using NSwag to generate client libraries but I haven't used it before so went with the safer option of manually writing it.
- Identity Server: Its set up but I ran out of time so there are no users or roles. The API client also has no functionality for authenticating.
- Validation: None of the models or domain entities are validated. For this I'd probably use FluentValidation and ASP.NET Core Model Validation (they work well together).
- Exception handling: Generally I find it useful to catch certain exceptions (like a ValidationException, and return a custom response to the client).
- Some sort of front-end: at least to test the API client library.