Wally.CleanArchitecture.Template
1.2.3
See the version list below for details.
dotnet new install Wally.CleanArchitecture.Template::1.2.3
Wally.CleanArchitecture.MicroService
[[TOC]]
ToDo
- Add
AggregateRoot
Shadow Properties
orAuditableEntity
abstract class for selectedAggregateRoot
andEntity
:
public DateTime Created { get; set; }
public string? CreatedBy { get; set; }
public DateTime? LastModified { get; set; }
public string? LastModifiedBy { get; set; }
ValueObject
abstract base:
public abstract class ValueObject
{
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, null) || left.Equals(right);
}
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
public override int GetHashCode()
{
return GetEqualityComponents()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
// Other utility methods
}
- Create
DependencyInjection
class inInfrastructure
- Use Aspect Oriented Programming
Components
Swagger
UI: https://localhost:7197/swagger/index.html
Serilog
serilog.json
{
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.ApplicationInsights"
],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Information"
}
},
"WriteTo": [
{
"Name": "Debug"
},
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Properties:j}{NewLine}{Exception}{NewLine}"
}
},
{
"Name": "ApplicationInsights",
"Args": {
"instrumentationKey": "---",
"restrictedToMinimumLevel": "Information",
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
}
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "---",
"tableName": "Log",
"columnOptionsSection": {
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "Properties" ]
}
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Wally.CleanArchitecture"
}
}
}
Health Checks
AppVer: https://localhost:7197 Health: https://localhost:7197/healthchecks
UI: https://localhost:7197/healthchecks-ui UI cfg: https://localhost:7197/healthchecks-api/ui-settings
API: https://localhost:7197/healthchecks-api
Webhooks: https://localhost:7197/healthchecks-webhooks
appsettings.json
...
"HealthChecks-UI": {
"DisableMigrations": true,
"HealthChecks": [
{
"Name": "Poll Manager",
"Uri": "/healthChecks"
}
],
"Webhooks": [
{
"Name": "",
"Uri": "",
"Payload": "",
"RestoredPayload": ""
}
],
"EvaluationTimeOnSeconds": 10,
"MinimumSecondsBetweenFailureNotifications": 60,
"MaximumExecutionHistoriesPerEndpoint": 15,
"HealthCheckDatabaseConnectionString": "Data Source=healthChecks"
}
...
Known Issues:
Mapster
Known Issuees:
System.MissingMethodException: Constructor on type 'Mapster.EFCore.MapsterAsyncEnumerable`1[[Wally.CleanArchitecture.Contracts.Responses.Users.GetUserResponse, Wally.CleanArchitecture.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, Object[] args)
at Mapster.EFCore.MapsterQueryableProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.SingleAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Wally.CleanArchitecture.Persistence.Repository`1.GetAsync[TResult](Guid id, CancellationToken cancellationToken) in C:\repo\wally\wally.CleanArchitecture\src\Wally.CleanArchitecture.Persistence\Repository.cs:line 0
at Wally.CleanArchitecture.Application.Users.Queries.GetUserQueryHandler.HandleAsync(GetUserQuery query, CancellationToken cancellationToken) in C:\repo\wally\wally.CleanArchitecture\src\Wally.CleanArchitecture.Application\Users\Queries\GetUserQueryHandler.cs:line 19
at Wally.CleanArchitecture.Application.Abstractions.QueryHandler`2.Handle(TQuery query, CancellationToken cancellationToken) in C:\repo\wally\wally.CleanArchitecture\src\Wally.CleanArchitecture.Application\Abstractions\QueryHandler.cs:line 16
at MediatR.Internal.RequestHandlerWrapperImpl`2.<>c__DisplayClass1_0.<Handle>g__Handler|0()
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
AutoMapper
Tests
curl -X GET "https://localhost:7197/Users/3fa85f64-5717-4562-b3fc-2c963f66afa6" -H "accept:
application/json;odata.metadata=minimal;odata.streaming=true"
curl -X GET "https://localhost:7197/Users" -H "accept: application/json;odata.metadata=minimal;odata.streaming=true"
curl -X GET "https://localhost:7197/Users?$orderby=Id&$top=1" -H "accept:
application/json;odata.metadata=minimal;odata.streaming=true"
curl -X GET "https://localhost:7197/Users?$count=true&$orderby=Id&$top=0" -H "accept:
application/json;odata.metadata=minimal;odata.streaming=true"
curl -X GET "https://localhost:7197/Users?$count=true&$orderby=Id&$skip=2&$top=2" -H "accept:
application/json;odata.metadata=minimal;odata.streaming=true"
{
"items":[
{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa8","name":"testDbData3"}
],
"pageInfo":{
"index":1,
"size":2,
"totalItems":3
}
}
curl -X GET "https://localhost:7197/Users?$orderby=Name%20desc&$top=3" -H "accept: application/json;odata.metadata=minimal;odata.streaming=true"
{
"items":[
{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa8","name":"testDbData3"},
{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa7","name":"testDbData2"},
{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","name":"testDbData1"}
],
"pageInfo":{
"index":0,
"size":3,
"totalItems":3
}
}
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.3.2615 | 36 | 6/27/2024 |
1.3.2584 | 214 | 5/26/2024 |
1.3.2579 | 115 | 5/25/2024 |
1.3.2575 | 81 | 5/25/2024 |
1.3.2571 | 80 | 5/25/2024 |
1.3.2570 | 111 | 5/24/2024 |
1.3.2563 | 113 | 5/23/2024 |
1.3.2562 | 68 | 5/23/2024 |
1.3.2560 | 95 | 5/22/2024 |
1.3.2557 | 108 | 5/21/2024 |
1.3.2554 | 74 | 5/21/2024 |
1.3.2551 | 104 | 5/20/2024 |
1.3.2547 | 145 | 5/17/2024 |
1.3.2537 | 84 | 5/16/2024 |
1.3.2536 | 72 | 5/16/2024 |
1.3.2535 | 233 | 5/9/2024 |
1.3.2527 | 81 | 4/26/2024 |
1.3.2510 | 86 | 4/24/2024 |
1.3.2490 | 133 | 4/13/2024 |
1.3.2473 | 138 | 4/8/2024 |
1.3.2471 | 150 | 4/8/2024 |
1.3.2431 | 160 | 4/4/2024 |
1.3.2404 | 300 | 3/22/2024 |
1.3.2401 | 156 | 3/21/2024 |
1.3.2366 | 1,014 | 2/21/2024 |
1.3.2365 | 360 | 2/21/2024 |
1.3.2347 | 681 | 2/9/2024 |
1.3.2248 | 2,234 | 12/6/2023 |
1.3.2243 | 548 | 12/5/2023 |
1.3.2227 | 921 | 11/26/2023 |
1.3.2222 | 667 | 11/26/2023 |
1.3.2212 | 803 | 11/18/2023 |
1.3.2209 | 514 | 11/17/2023 |
1.3.2172 | 1,079 | 11/1/2023 |
1.3.2166 | 744 | 10/30/2023 |
1.3.2163 | 705 | 10/29/2023 |
1.3.2149 | 973 | 10/18/2023 |
1.3.2137 | 1,114 | 10/3/2023 |
1.3.2108 | 740 | 9/25/2023 |
1.3.2093 | 776 | 9/17/2023 |
1.3.2086 | 803 | 8/27/2023 |
1.3.2085 | 873 | 8/27/2023 |
1.3.2042 | 968 | 6/23/2023 |
1.3.2023 | 851 | 6/15/2023 |
1.3.1982 | 934 | 5/28/2023 |
1.3.1974 | 790 | 5/26/2023 |
1.3.1954 | 805 | 5/20/2023 |
1.3.1948 | 841 | 5/18/2023 |
1.3.1947 | 666 | 5/18/2023 |
1.3.1941 | 876 | 5/17/2023 |
1.3.1933 | 926 | 5/15/2023 |
1.3.1913 | 847 | 5/12/2023 |
1.3.1912 | 969 | 5/12/2023 |
1.3.1861 | 1,112 | 3/24/2023 |
1.3.1860 | 987 | 3/24/2023 |
1.3.1850 | 862 | 3/18/2023 |
1.3.1847 | 992 | 3/15/2023 |
1.3.1846 | 921 | 3/14/2023 |
1.3.1844 | 1,004 | 3/14/2023 |
1.3.1835 | 802 | 3/9/2023 |
1.3.1834 | 832 | 3/9/2023 |
1.3.1832 | 783 | 3/9/2023 |
1.3.1829 | 874 | 3/9/2023 |
1.3.1817 | 945 | 3/3/2023 |
1.2.1814 | 1,224 | 2/27/2023 |
1.2.1811 | 1,067 | 2/20/2023 |
1.2.1767 | 1,140 | 1/18/2023 |
1.2.1760 | 1,165 | 1/14/2023 |
1.2.1743 | 1,208 | 12/25/2022 |
1.2.1701 | 1,220 | 11/23/2022 |
1.2.1690 | 1,225 | 11/14/2022 |
1.2.1689 | 1,227 | 11/14/2022 |
1.2.1687 | 1,217 | 11/14/2022 |
1.2.1685 | 1,193 | 11/11/2022 |
1.2.8 | 1,211 | 11/1/2022 |
1.2.7 | 1,022 | 11/1/2022 |
1.2.6 | 1,250 | 11/1/2022 |
1.2.5 | 1,363 | 10/4/2022 |
1.2.4 | 1,343 | 9/9/2022 |
1.2.3 | 1,433 | 6/9/2022 |
1.2.2 | 1,233 | 6/9/2022 |
1.2.1 | 1,234 | 4/17/2022 |
1.2.0 | 1,427 | 4/17/2022 |
1.1.1553 | 1,370 | 6/10/2022 |
1.1.1516 | 1,223 | 4/17/2022 |
1.1.1515 | 1,431 | 4/17/2022 |
1.1.0 | 1,492 | 3/22/2022 |
0.1.1514 | 1,356 | 4/17/2022 |
0.1.1513 | 1,331 | 4/16/2022 |
0.1.1512 | 1,343 | 4/16/2022 |
0.1.1509 | 1,455 | 4/16/2022 |
0.1.1487 | 1,377 | 3/29/2022 |
0.1.1471 | 1,365 | 3/20/2022 |
0.1.1470 | 1,501 | 3/20/2022 |
0.1.1463 | 1,425 | 3/20/2022 |
0.1.1461 | 1,355 | 3/19/2022 |
0.1.1454 | 1,473 | 3/19/2022 |
0.1.1452 | 1,495 | 3/19/2022 |
0.1.1437 | 1,367 | 3/13/2022 |
0.1.1433 | 1,556 | 2/15/2022 |
0.1.1426 | 1,625 | 2/10/2022 |
0.1.1422 | 1,539 | 2/10/2022 |
0.1.1398 | 1,473 | 1/22/2022 |
0.1.1393 | 1,320 | 1/16/2022 |
0.1.1391 | 1,516 | 1/16/2022 |
0.1.1388 | 1,590 | 1/16/2022 |