Skip to content

Commit 7bce405

Browse files
part 4.
part 4.
1 parent 09badc8 commit 7bce405

File tree

13 files changed

+725
-454
lines changed

13 files changed

+725
-454
lines changed

UserManagement.API/ClientApp/package-lock.json

Lines changed: 465 additions & 439 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UserManagement.API/ClientApp/package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@
1111
},
1212
"private": true,
1313
"dependencies": {
14-
"@angular/animations": "~10.1.0",
15-
"@angular/common": "~10.1.0",
16-
"@angular/compiler": "~10.1.0",
17-
"@angular/core": "~10.1.0",
18-
"@angular/forms": "~10.1.0",
19-
"@angular/platform-browser": "~10.1.0",
20-
"@angular/platform-browser-dynamic": "~10.1.0",
21-
"@angular/router": "~10.1.0",
14+
"@angular/animations": "~10.2.0",
15+
"@angular/common": "~10.2.0",
16+
"@angular/compiler": "~10.2.0",
17+
"@angular/core": "~10.2.0",
18+
"@angular/forms": "~10.2.0",
19+
"@angular/platform-browser": "~10.2.0",
20+
"@angular/platform-browser-dynamic": "~10.2.0",
21+
"@angular/router": "~10.2.0",
2222
"rxjs": "~6.6.0",
2323
"tslib": "^2.0.0",
2424
"zone.js": "~0.10.2"
2525
},
2626
"devDependencies": {
27-
"@angular-devkit/build-angular": "~0.1001.0",
28-
"@angular/cli": "~10.1.0",
29-
"@angular/compiler-cli": "~10.1.0",
30-
"@types/node": "^12.11.1",
27+
"@angular-devkit/build-angular": "^0.1002.0",
28+
"@angular/cli": "~10.2.0",
29+
"@angular/compiler-cli": "~10.2.0",
3130
"@types/jasmine": "~3.5.0",
3231
"@types/jasminewd2": "~2.0.3",
32+
"@types/node": "^12.11.1",
3333
"codelyzer": "^6.0.0",
3434
"jasmine-core": "~3.6.0",
3535
"jasmine-spec-reporter": "~5.0.0",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace UserManagement.Application.Common.Behaviors
2+
{
3+
using MediatR.Pipeline;
4+
using Microsoft.Extensions.Logging;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
8+
public class LoggingBehaviour<TRequest> : IRequestPreProcessor<TRequest>
9+
{
10+
private readonly ILogger _logger;
11+
12+
public LoggingBehaviour(ILogger<TRequest> logger)
13+
{
14+
_logger = logger;
15+
}
16+
17+
public async Task Process(TRequest request, CancellationToken cancellationToken)
18+
{
19+
var requestName = typeof(TRequest).Name;
20+
string userName = string.Empty;
21+
22+
await Task.Run(() => _logger.LogInformation("UserManagement Request: {Name} {@UserName} {@Request}",
23+
requestName, userName, request));
24+
}
25+
}
26+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace UserManagement.Application.Common.Behaviors
2+
{
3+
using MediatR;
4+
using Microsoft.Extensions.Logging;
5+
using System.Diagnostics;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using UserManagement.Application.Common.Interfaces;
9+
public class PerformanceBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
10+
{
11+
private readonly Stopwatch _timer;
12+
private readonly ILogger<TRequest> _logger;
13+
private readonly IConfigConstants _constact;
14+
15+
public PerformanceBehaviour(ILogger<TRequest> logger, IConfigConstants constants)
16+
{
17+
_timer = new Stopwatch();
18+
_logger = logger;
19+
_constact = constants;
20+
}
21+
22+
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
23+
{
24+
_timer.Start();
25+
26+
var response = await next();
27+
28+
_timer.Stop();
29+
30+
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
31+
32+
if (elapsedMilliseconds > _constact.LongRunningProcessMilliseconds)
33+
{
34+
var requestName = typeof(TRequest).Name;
35+
var userName = string.Empty;
36+
_logger.LogWarning("UserManagement Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserName} {@Request}",
37+
requestName, elapsedMilliseconds, userName, request);
38+
}
39+
40+
return response;
41+
}
42+
}
43+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace UserManagement.Application.Common.Behaviours
2+
{
3+
using MediatR;
4+
using Microsoft.Extensions.Logging;
5+
using System;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
public class UnhandledExceptionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
9+
{
10+
private readonly ILogger<TRequest> _logger;
11+
12+
public UnhandledExceptionBehaviour(ILogger<TRequest> logger)
13+
{
14+
_logger = logger;
15+
}
16+
17+
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
18+
{
19+
try
20+
{
21+
return await next();
22+
}
23+
catch (Exception ex)
24+
{
25+
var requestName = typeof(TRequest).Name;
26+
27+
_logger.LogError(ex, "UserManagement Request: Unhandled Exception for Request {Name} {@Request}", requestName, request);
28+
29+
throw;
30+
}
31+
}
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace UserManagement.Application.Common.Behaviours
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using FluentValidation;
8+
using MediatR;
9+
using ValidationException = UserManagement.Application.Common.Exceptions.ValidationException;
10+
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
11+
where TRequest : IRequest<TResponse>
12+
{
13+
private readonly IEnumerable<IValidator<TRequest>> _validators;
14+
15+
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators)
16+
{
17+
_validators = validators;
18+
}
19+
20+
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
21+
{
22+
if (_validators.Any())
23+
{
24+
var context = new ValidationContext<TRequest>(request);
25+
26+
var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
27+
var failures = validationResults.SelectMany(r => r.Errors).Where(f => f != null).ToList();
28+
29+
if (failures.Count != 0)
30+
throw new ValidationException(failures);
31+
}
32+
return await next();
33+
}
34+
}
35+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace UserManagement.Application.Common.Exceptions
2+
{
3+
using System;
4+
public class NotFoundException : Exception
5+
{
6+
public NotFoundException()
7+
: base()
8+
{
9+
}
10+
11+
public NotFoundException(string message)
12+
: base(message)
13+
{
14+
}
15+
16+
public NotFoundException(string message, Exception innerException)
17+
: base(message, innerException)
18+
{
19+
}
20+
21+
public NotFoundException(string name, object key)
22+
: base($"Entity \"{name}\" ({key}) was not found.")
23+
{
24+
}
25+
}
26+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace UserManagement.Application.Common.Exceptions
2+
{
3+
using FluentValidation.Results;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
public class ValidationException : Exception
8+
{
9+
public ValidationException()
10+
: base("One or more validation failures have occurred.")
11+
{
12+
Errors = new Dictionary<string, string[]>();
13+
}
14+
15+
public ValidationException(IEnumerable<ValidationFailure> failures)
16+
: this()
17+
{
18+
Errors = failures
19+
.GroupBy(e => e.PropertyName, e => e.ErrorMessage)
20+
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray());
21+
}
22+
23+
public IDictionary<string, string[]> Errors { get; }
24+
}
25+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace UserManagement.Application.Common.Mappings
2+
{
3+
using AutoMapper;
4+
public interface IMapFrom<T>
5+
{
6+
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType()).ReverseMap();
7+
}
8+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace UserManagement.Application.Common.Mappings
2+
{
3+
using AutoMapper;
4+
using System;
5+
using System.Linq;
6+
using System.Reflection;
7+
8+
public class MappingProfile : Profile
9+
{
10+
public MappingProfile()
11+
{
12+
ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
13+
}
14+
15+
private void ApplyMappingsFromAssembly(Assembly assembly)
16+
{
17+
var types = assembly.GetExportedTypes()
18+
.Where(t => t.GetInterfaces().Any(i =>
19+
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>)))
20+
.ToList();
21+
22+
foreach (var type in types)
23+
{
24+
var instance = Activator.CreateInstance(type);
25+
26+
var methodInfo = type.GetMethod("Mapping")
27+
?? type.GetInterface("IMapFrom`1").GetMethod("Mapping");
28+
29+
methodInfo?.Invoke(instance, new object[] { this });
30+
31+
}
32+
}
33+
}
34+
}
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netstandard2.0</TargetFramework>
4+
<TargetFramework>netstandard2.1</TargetFramework>
55
</PropertyGroup>
66

7+
<ItemGroup>
8+
<PackageReference Include="AutoMapper" Version="10.1.1" />
9+
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
10+
<PackageReference Include="FluentValidation" Version="9.2.2" />
11+
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="9.2.0" />
12+
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.9" />
14+
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.9" />
15+
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\UserManagement.Domain\UserManagement.Domain.csproj" />
20+
</ItemGroup>
21+
722
</Project>

UserManagement.Domain/UserManagement.Domain.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netstandard2.0</TargetFramework>
4+
<TargetFramework>netstandard2.1</TargetFramework>
55
</PropertyGroup>
66

77
<ItemGroup>

UserManagement.Persistence/UserManagement.Persistence.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netstandard2.0</TargetFramework>
4+
<TargetFramework>netstandard2.1</TargetFramework>
55
</PropertyGroup>
66

77
<ItemGroup>

0 commit comments

Comments
 (0)