UPDATED: Boilerplate został zmigrowany do .NET 6
!
Boilerplate to kawałek kodu, który w szybki sposób pomaga wystartować pisanie kodu. Pewnego rodzaju szablon. Zamiast startować z pustym projektem i dodawać za każdym razem od nowa te same cegiełki, możemy posłużyć się boilerplatem, który te cegiełki już zawiera.
Ostatnimi czasy kilka razy tworzyłem od początku aplikację w .NET Core, a w ramach tej aplikacji odpowiedni zestaw projektów oraz komponentów. Za każdym razem schemat postępowania był bardzo podobny – w jednym projekcie API, w kolejnym projekcie warstwa dostępu do danych oraz kawałek biznesu, następnie projekty z testami. Typ projektu determinował załączone NuGetowe paczki, konfigurację oraz klasy bazowe, które po wielokroć były identyczne. Na koniec “strażnicy” jakości kodu, oni również identyczni w każdej z nowopowstałych aplikacji. Schemat się powtarzał.
Postanowiłem stworzyć wzorcową aplikację (tytułowego boilerplate), która zawierać będzie zestaw zwyczajowych komponentów. Jeśli jakiś komponent jest nadmiarowy, niepotrzebny dla nowego rozwiązania które rozpoczynam, to najzwyczajniej go usuwam. Znacznie szybciej redukować kod źródłowy aplikacji niż dodawać. To rozwiązanie pozwala mi znacznie szybciej wystartować projekt, a co za tym idzie zaoszczędzić czas.
Boilerplate dostępny jest na GitHub. Korzystać z niego można do woli, zapraszam.
Zawartość
- Autofac
- Swagger + Swashbuckle
- FeatureManagement (Feature Flags, Feature Toggles)
- HealthChecks
- EF Core
- Testy
- Jakość kodu
- editorconfig
- Analizery (Microsoft.CodeAnalysis.Analyzers, Microsoft.AspNetCore.Mvc.Api.Analyzers)
- Reguły
- Pokrycie kodu
- Docker
- Dockerfile
- Docker-compose
mysql:8
(z zainicjalizowaną bazą)mcr.microsoft.com/mssql/server:2017-latest
(z zainicjalizowaną bazą)netcore-boilerplate:local
- Serilog
- Sink: Async
- Enrich: CorrelationId
- DbUp jako narzędzie do wdrażania zmian schematu bazy danych
- Ciągła integracja (CI)
Architektura
Api
HappyCode.NetCoreBoilerplate.Api
- Klasa startowa – Startup.cs
- MvcCore
- DbContext (MySQL)
- DbContext (MsSQL)
- Swagger
- SwaggerUI (Swashbuckle)
- HostedService
- HttpClient
- HealthCheck
- Filtry
- Prosty filtr autoryzacji wykorzystujący ApiKey – ApiKeyAuthorizationFilter.cs
- Filtr walidujący ModelState – ValidateModelStateFilter.cs
- Globalny filtr wyjątków – HttpGlobalExceptionFilter.cs
- Rejestracja zależności – ContainerConfigurator.cs
- Konfiguracja
Serilog
– ContainerConfigurator.cs - Przykładowy kontroler – EmployeesController.cs
- Zadanie działające w tle – PingWebsiteBackgroundService.cs
Core
HappyCode.NetCoreBoilerplate.Core
- Prosty DbContext – EmployeesContext.cs
- Przykładowe repozytorium – EmployeeRepository.cs
DbUp
HappyCode.NetCoreBoilerplate.Db
- Aplikacja konsolowa do uruchomienia procesu wdrożenia zmian bazy danych – Program.cs
- Przykładowe skrypty zmian, wersja
.sql
oraz.cs
– S001_AddCarTypesTable.sql, S002_ModifySomeRows.cs
Testy
Testy integracyjne
HappyCode.NetCoreBoilerplate.Api.IntegrationTests
- Start serwera w pamięci – TestServerClientFixture.cs
- Klasa startowa z bazą działającą w pamięci (InMemory) – TestStartup.cs
- Prosty “wypełniacz” bazy danych – EmployeeContextDataFeeder.cs
- Przykłady testów integracyjnych – EmployeesTests.cs
Testy jednostkowe
HappyCode.NetCoreBoilerplate.Api.UnitTests
- Przykłady testów jednostkowych kontrolera – EmployeesControllerTests.cs
HappyCode.NetCoreBoilerplate.Core.UnitTests
- Klasy pozwalające imitować DbContext – TestAsyncEnumerable.cs, TestAsyncEnumerator.cs, TestAsyncQueryProvider.cs
- Metoda rozszerzająca pozwalająca w szybki sposób imitować DbSet – EnumerableExtensions.cs
- Przykładowe testy jednostkowe repozytorium – EmployeeRepositoryTests.cs
Testy obciążenia
HappyCode.NetCoreBoilerplate.Api.LoadTests
- Klasa bazowa – LoadTestsBase.cs
- Przykłady testów obciążenia – EmployeesControllerTests.cs
Repozytorium
https://github.com/lkurzyniec/netcore-boilerplate
Hej!
Jeszcze poproszę multitenancy :)
Pozdrawiam
Adam,
To już we własnym zakresie. Natomiast nic nie stoi na przeszkodzie, aby wykorzystać ten boilerplate do zbudowania takiej aplikacji/systemu.
Dla kolegi Adama szukającego multitenancy. https://aspnetboilerplate.com/
CrazyBaran,
W moim odczuciu multitenancy da się zapewnić tylko i wyłącznie odpowiednią architekturą całego systemu/aplikacji. Zarówno mój boilerplate, jak i generator z Twojego linku, to tylko jeden element skomplikowanej układanki, na który nie ma szablonów. Każdy system tego typu należy zaprojektować indywidualnie patrząc na wymagania.
Niemniej jednak, dzięki za link.
Świetny kawałek kodu :)
DrStrange,
Dziękuję, miło mi to słyszeć.
Pamiętaj, że zawsze możesz kliknąć gwiazdkę na GitHub.
Czy jest jakiś konkretny cel w tym że w projekcie jest zarówno msSql jak i MySql ? Czy tylko po to żeby pokazać jak używać jednego i drugiego ?
Druga sprawa to różna jest konstrukcja Employe od Cars (controller employer dostaje się do danych przy pomocy repository, a cars -> services->dbContext) Czy jest tego jakiś konkretny zamysł ? czy przedstawione są poprostu 2 możliwości konstrukcji aplikacji i należy zdecydować się na wygodniejszą i usunąć drugą ?
Marcin,
W obu przypadkach dobrze dedukujesz.
Wyjaśniając intencje pierwszego przypadku, to chciałem pokazać jak w prosty sposób można korzystać z obu silników bazodanowych w .NET Core.
W drugim natomiast, że niekoniecznie należy trzymać się schematu db -> repository -> service -> controller, lecz samemu zdecydować i może iść na skróty, a może jednak wykorzystać schemat. W moim przypadku to bardzo małe API więc idę na skróty, natomiast dla większych aplikacji zdecydowanie zalecałbym skorzystać ze schematu.
Dzięki za szybką odpowiedź. W takim razie wykorzystam sytuację, że kontakt z autorem jest taki dobry i…
ściągnąłem projekt, uruchomiłem go poprzez docker-compose up. Jednak /health pokazuje, że nie może połączyć się z bazami danych.
MySql podczas uruchomienia ogłasza:
[Server] –initialize specified but the data directory has files in it. Aborting.
[Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
a SqlServer ogłasza że nie może się zalogować z tymi danymi ponieważ nie ma user’a o nazwie User.
Wiesz może w czym może być problem ? odpalam na macOS
Marcin,
Zaglądnij tutaj we wtorek, powinienem coś wiedzieć. Na razie nie mam dostępu do komputera.
Dla mysql problem leżał w volume docker’a.
Musiałem zmienić na taką ścieżkę:
volumes:
– local_mysql:/var/opt/mysql/data
, bo do var/lib/mysql nie miał dostępu.
Dla sqlServer to juz nie wiem co było powodem bo wystarczyła mi jedna baza :D
Marcin,
Zgodnie z tym co widzę w dokumentacji obrazu (https://hub.docker.com/_/mysql, „Where to Store Data”) ścieżka
/var/lib/mysql
jest poprawną ścieżką.Puściłem u siebie lokalnie od zera cały
docker-compouse
i poszło elegancko bez przeszkód/błędów.Cześć,
Chciałbym zapytać o możliwość uzyskania kodu twojego boilerplate na innej licencji, niż GPL 2.0. Chciałbym wykorzystać twój kod w komercyjnym projekcie, a co za tym idzie dział prawny będzie mnie maglował o to, żeby nie musieć obejmować naszego kodu GPLem tylko dlatego, że użyjemy boilerplate’u na takiej licencji. Czy rozważałeś publikację na bardziej liberalnej licencji typu MIT, albo ewentualnie czy można uzyskać komercyjną licencję za pieniądze?
Grzegorz,
Licencja GPL-2.0 daje możliwość stosowania w projektach komercyjnych. Korzystaj!