Add project files.
This commit is contained in:
parent
4470175f26
commit
5ac06a4e15
25
Lib.Architecture.BuildingBlocks.sln
Normal file
25
Lib.Architecture.BuildingBlocks.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34309.116
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib.Architecture.BuildingBlocks", "Lib.Architecture.BuildingBlocks\Lib.Architecture.BuildingBlocks.csproj", "{FBB6B156-0EB5-4728-8B4D-7E761F7C7506}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FBB6B156-0EB5-4728-8B4D-7E761F7C7506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FBB6B156-0EB5-4728-8B4D-7E761F7C7506}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FBB6B156-0EB5-4728-8B4D-7E761F7C7506}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FBB6B156-0EB5-4728-8B4D-7E761F7C7506}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {48281157-94C3-4A0A-B0A9-D9BB2A94DBA7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
34
Lib.Architecture.BuildingBlocks/Application/CommandResult.cs
Normal file
34
Lib.Architecture.BuildingBlocks/Application/CommandResult.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public class CommandResult : ICommandResult
|
||||
{
|
||||
public CommandResult() { }
|
||||
protected ActionResult ViewModelResult { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public object Result { get; set; }
|
||||
public ActionResult ViewModel => ViewModelResult;
|
||||
public IReadOnlyCollection<Notification> Messages { get; set; }
|
||||
|
||||
public CommandResult(bool success)
|
||||
{
|
||||
Success = success;
|
||||
}
|
||||
public CommandResult(bool success, IReadOnlyCollection<Notification> messages)
|
||||
{
|
||||
Success = success;
|
||||
Messages = messages;
|
||||
}
|
||||
public CommandResult(bool success, object result)
|
||||
{
|
||||
Result = result;
|
||||
Success = success;
|
||||
}
|
||||
public void ValidationErrors(IEnumerable<Notification> notifications)
|
||||
{
|
||||
ViewModelResult = new PreconditionFailedObjectResult(notifications);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Lib.Architecture.BuildingBlocks/Application/QueryResult.cs
Normal file
23
Lib.Architecture.BuildingBlocks/Application/QueryResult.cs
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public class QueryResult : IQueryResult
|
||||
{
|
||||
public QueryResult() { }
|
||||
public QueryResult(bool success, IReadOnlyCollection<Notification> messages)
|
||||
{
|
||||
Success = success;
|
||||
Messages = messages;
|
||||
}
|
||||
|
||||
public QueryResult(bool success, dynamic result)
|
||||
{
|
||||
Success = success;
|
||||
Result = result;
|
||||
}
|
||||
|
||||
public bool Success { get; set; }
|
||||
public dynamic Result { get; set; }
|
||||
public IReadOnlyCollection<Notification> Messages { get; set; }
|
||||
}
|
||||
}
|
||||
9
Lib.Architecture.BuildingBlocks/Commands/ICommand.cs
Normal file
9
Lib.Architecture.BuildingBlocks/Commands/ICommand.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface ICommand { bool Validate(); }
|
||||
public interface ICommandResult { }
|
||||
}
|
||||
21
Lib.Architecture.BuildingBlocks/Commands/ICommandHandler.cs
Normal file
21
Lib.Architecture.BuildingBlocks/Commands/ICommandHandler.cs
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface ICommandHandler<Tin> where Tin : ICommand
|
||||
{
|
||||
ValueTask<ICommandResult> ExecuteAsync(Tin command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
public interface IComponentHandler<in TIn> where TIn : ICommand
|
||||
{
|
||||
ValueTask ExecuteAsync(TIn command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
//out
|
||||
public interface IComponentHandler<in TIn, TOut> where TIn : ICommand
|
||||
where TOut : class
|
||||
{
|
||||
ValueTask<ICommandResult> ExecuteAsync<TOut>(TIn command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IAggregateRoot
|
||||
{
|
||||
Guid Id { get; }
|
||||
}
|
||||
public interface IAggregateRoot<out TType> where TType : new()
|
||||
{
|
||||
TType Id { get; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IDomainEvent
|
||||
{
|
||||
DateTime OccorredOn { get; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IDomainEventPublisher<TEvent> where TEvent : IEvent
|
||||
{
|
||||
ValueTask Publish(TEvent @event, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
12
Lib.Architecture.BuildingBlocks/Contracts/Events/IEvent.cs
Normal file
12
Lib.Architecture.BuildingBlocks/Contracts/Events/IEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IEventHandler<T> where T : IDomainEvent
|
||||
{
|
||||
ValueTask Execute(T @event, CancellationToken ctx);
|
||||
}
|
||||
public interface IEventHandler<TIn, TOut> where TIn : IDomainEvent where TOut : BaseEntity
|
||||
{
|
||||
ValueTask<TOut> Execute(TIn @event, CancellationToken ctx);
|
||||
}
|
||||
}
|
||||
48
Lib.Architecture.BuildingBlocks/Endpoints/BaseEndpoint.cs
Normal file
48
Lib.Architecture.BuildingBlocks/Endpoints/BaseEndpoint.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.Blueprint.External
|
||||
{
|
||||
public class BaseEndpoint
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public Uri Uri { get; set; }
|
||||
public string Token { get; set; }
|
||||
public string APIKey { get; set; }
|
||||
public string APISecret { get; set; }
|
||||
public string APIName { get; set; }
|
||||
|
||||
}
|
||||
public class AccessLog
|
||||
{
|
||||
private Guid CorrelationId { get; set; } = new Guid();
|
||||
protected DateTime DateTime { get; set; } = DateTime.Now;
|
||||
protected string Method { get; set; }
|
||||
protected object Request { get; set; }
|
||||
protected string User { get; set; }
|
||||
|
||||
public void GetCurrentMethodExecution()
|
||||
{
|
||||
var method = System.Reflection.MethodBase.GetCurrentMethod();
|
||||
|
||||
Method = string.Format("{0}.{1}({2})",
|
||||
method.ReflectedType.FullName, method.Name,
|
||||
string.Join(",", method.GetParameters().
|
||||
Select(o => string.Format("{0} {1}", o.ParameterType, o.Name)).
|
||||
ToArray()));
|
||||
}
|
||||
|
||||
public void SetCurrentRequestExecution(string request)
|
||||
{
|
||||
|
||||
}
|
||||
public void SetCurrentUserExecution(string user)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Lib.Architecture.BuildingBlocks/Entity/BaseEntity.cs
Normal file
13
Lib.Architecture.BuildingBlocks/Entity/BaseEntity.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public class BaseEntity<TValidator> : Notificator where TValidator : IValidator, new()
|
||||
{
|
||||
public virtual DateOnly Created { get; set; }
|
||||
}
|
||||
public class BaseEntity : Notificator
|
||||
{
|
||||
public virtual DateOnly Created { get; set; }
|
||||
}
|
||||
}
|
||||
40
Lib.Architecture.BuildingBlocks/Entity/ValueObject.cs
Normal file
40
Lib.Architecture.BuildingBlocks/Entity/ValueObject.cs
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public abstract class ValueObject
|
||||
{
|
||||
protected abstract IEnumerable<object> GetEqualityComponents();
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
||||
if (obj is null || obj.GetType() != GetType())
|
||||
return false;
|
||||
|
||||
var other = (ValueObject)obj;
|
||||
|
||||
return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return GetEqualityComponents()
|
||||
.Select(x => x is not null ? x.GetHashCode() : 0)
|
||||
.Aggregate((x, y) => x ^ y);
|
||||
}
|
||||
|
||||
protected static bool EqualOperator(ValueObject left, ValueObject right)
|
||||
{
|
||||
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
|
||||
return false;
|
||||
|
||||
return ReferenceEquals(left, right) || left.Equals(right);
|
||||
}
|
||||
|
||||
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
|
||||
{
|
||||
return !(EqualOperator(left, right));
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects
|
||||
}
|
||||
16
Lib.Architecture.BuildingBlocks/Events/DomainEvents.cs
Normal file
16
Lib.Architecture.BuildingBlocks/Events/DomainEvents.cs
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
//Class For Create Domain Events
|
||||
public record DomainEvent<TEntity>(TEntity Entity) : IDomainEvent where TEntity : IEvent
|
||||
{
|
||||
public DateTime OccorredOn => DateTime.Now;
|
||||
public Guid CorrelationId { get; init; } = Guid.NewGuid();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return typeof(TEntity).Name;
|
||||
}
|
||||
internal ICollection<IDomainEvent> DomainEvents { get; } = new List<IDomainEvent>();
|
||||
}
|
||||
}
|
||||
63
Lib.Architecture.BuildingBlocks/Helpers/ApiResponseHelper.cs
Normal file
63
Lib.Architecture.BuildingBlocks/Helpers/ApiResponseHelper.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using Newtonsoft.Json;
|
||||
using Refit;
|
||||
using System.Net;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Helpers
|
||||
{
|
||||
public static class ApiResponseHelper
|
||||
{
|
||||
public static void EvaluatePort<TPort>(Exception exception, TPort port)
|
||||
where TPort : INotFoundPort, IBusinessErrorPort, ITimeoutPort, INoContentPort,
|
||||
IUnauthorizedPort, IForbiddenPort, IInternalServerErrorPort, IBadRequestPort
|
||||
{
|
||||
if (exception is ApiException refitException)
|
||||
{
|
||||
dynamic? errorMessage = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(refitException.Content))
|
||||
{
|
||||
try
|
||||
{
|
||||
errorMessage = JsonConvert.DeserializeObject<string>(refitException.Content) ?? string.Empty;
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(refitException.Content))
|
||||
{
|
||||
errorMessage = JsonConvert.DeserializeObject<HttpError>(refitException.Content);
|
||||
}
|
||||
|
||||
if (errorMessage?.Error.Target is null)
|
||||
{
|
||||
errorMessage = Newtonsoft.Json.JsonConvert.DeserializeObject<GenericErrorResponse>(refitException.Content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (refitException.StatusCode == HttpStatusCode.InternalServerError)
|
||||
port.InternalServerError(errorMessage);
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.NotFound)
|
||||
port.NotFound(errorMessage);
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.Forbidden && errorMessage)
|
||||
port.Forbidden(errorMessage);
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.UnprocessableContent)
|
||||
port.BusinessError(errorMessage);
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.BadRequest)
|
||||
port.BadRequest(errorMessage);
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.NoContent)
|
||||
port.NoContentSuccess();
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.Unauthorized)
|
||||
port.Unauthorized();
|
||||
|
||||
else if (refitException.StatusCode == HttpStatusCode.Forbidden)
|
||||
port.Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
// ***********************************************************************
|
||||
// <copyright file="AuthenticatedHttpClientHandler.cs">
|
||||
// Heath
|
||||
// </copyright>
|
||||
// ***********************************************************************
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Helpers.Token
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to inject the token in all requests.
|
||||
/// </summary>
|
||||
public class AuthenticatedHttpClientHandler : DelegatingHandler
|
||||
{
|
||||
private readonly ITokenProvider _tokenProvider;
|
||||
|
||||
public AuthenticatedHttpClientHandler(ITokenProvider tokenProvider)
|
||||
{
|
||||
_tokenProvider = tokenProvider;
|
||||
}
|
||||
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var token = _tokenProvider.GetToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
}
|
||||
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
// ***********************************************************************
|
||||
// <copyright file="HttpContextTokenProvider.cs">
|
||||
// Heath
|
||||
// </copyright>
|
||||
// ***********************************************************************
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Helpers.Token
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to return the access token to controllers.
|
||||
/// </summary>
|
||||
public class HttpContextTokenProvider : ITokenProvider
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public HttpContextTokenProvider(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get token from headers.
|
||||
/// </summary>
|
||||
public string GetToken()
|
||||
{
|
||||
return _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
// ***********************************************************************
|
||||
// <copyright file="ITokenProvider.cs">
|
||||
// Heath
|
||||
// </copyright>
|
||||
// ***********************************************************************
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Helpers.Token
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for token provider.
|
||||
/// </summary>
|
||||
public interface ITokenProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Get token from headers.
|
||||
/// </summary>
|
||||
string GetToken();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Core.Blueprint.Mongo" Version="0.3.0-alpha0047" />
|
||||
<PackageReference Include="FluentValidation" Version="11.11.0" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
|
||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Refit" Version="8.0.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Security.Cryptography.Xml" Version="9.0.1" />
|
||||
<PackageReference Include="System.Text.Encodings.Web" Version="9.0.1" />
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
16
Lib.Architecture.BuildingBlocks/Messages/Command.cs
Normal file
16
Lib.Architecture.BuildingBlocks/Messages/Command.cs
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
using FluentValidation.Results;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public abstract class Command : Message
|
||||
{
|
||||
public DateTime Timestamp { get; private set; }
|
||||
public ValidationResult ValidationResult { get; set; }
|
||||
|
||||
protected Command()
|
||||
{
|
||||
Timestamp = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Lib.Architecture.BuildingBlocks/Messages/Event.cs
Normal file
12
Lib.Architecture.BuildingBlocks/Messages/Event.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public abstract class Event : Message
|
||||
{
|
||||
public DateTime Timestamp { get; private set; }
|
||||
|
||||
protected Event()
|
||||
{
|
||||
Timestamp = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Lib.Architecture.BuildingBlocks/Messages/Message.cs
Normal file
15
Lib.Architecture.BuildingBlocks/Messages/Message.cs
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public abstract class Message: Notificator
|
||||
{
|
||||
public string Result { get; protected set; }
|
||||
public string MessageType { get; protected set; }
|
||||
public Guid AggregateId { get; protected set; }
|
||||
|
||||
protected Message()
|
||||
{
|
||||
MessageType = GetType().Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public sealed class BadGatewayError: ObjectResult
|
||||
{
|
||||
|
||||
private const int DefaultStatusCode = StatusCodes.Status502BadGateway;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public BadGatewayError(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
|
||||
public void GatherException(Exception exception)
|
||||
{
|
||||
if (exception is AggregateException)
|
||||
{
|
||||
var agEx = exception as AggregateException;
|
||||
Message = string.Join(" | ", agEx.InnerExceptions.Select(e => e.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = exception.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public sealed class BadRequestError: ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status400BadRequest;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public BadRequestError(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
|
||||
public void GatherException(Exception exception)
|
||||
{
|
||||
if (exception is AggregateException)
|
||||
{
|
||||
var agEx = exception as AggregateException;
|
||||
Message = string.Join(" | ", agEx.InnerExceptions.Select(e => e.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = exception.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class BusinessError
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public BusinessError(string key, string message)
|
||||
{
|
||||
Key = key;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public BusinessError(Exception coreException, string key)
|
||||
{
|
||||
Key = key;
|
||||
Message = coreException.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
// ***********************************************************************
|
||||
// <copyright file="ErrorDetailsDto.cs">
|
||||
// Heath
|
||||
// </copyright>
|
||||
// ***********************************************************************
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks;
|
||||
|
||||
/// <summary>
|
||||
/// The service error details transfer object.
|
||||
/// </summary>
|
||||
public class ErrorDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the service error code.
|
||||
/// </summary>
|
||||
|
||||
public string? ErrorCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the service error message.
|
||||
/// </summary>
|
||||
public string? Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the service target.
|
||||
/// </summary>
|
||||
public string? Target { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public sealed class GatewayTimeoutError: ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status504GatewayTimeout;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public GatewayTimeoutError(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
|
||||
public void GatherException(Exception exception)
|
||||
{
|
||||
if (exception is AggregateException)
|
||||
{
|
||||
var agEx = exception as AggregateException;
|
||||
Message = string.Join(" | ", agEx.InnerExceptions.Select(e => e.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = exception.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Lib.Architecture.BuildingBlocks;
|
||||
|
||||
public class GenericErrorResponse
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Title { get; set; }
|
||||
public int Status { get; set; }
|
||||
public Dictionary<string, List<string>> Errors { get; set; }
|
||||
public string TraceId { get; set; }
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
// ***********************************************************************
|
||||
// <copyright file="HttpErrorDto.cs">
|
||||
// Heath
|
||||
// </copyright>
|
||||
// ***********************************************************************
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks;
|
||||
|
||||
/// <summary>
|
||||
/// The service HTTP error data transfer object.
|
||||
/// </summary>
|
||||
public class HttpError
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the error.
|
||||
/// </summary>
|
||||
public ErrorDetails Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="HttpError{TMessage}"/>
|
||||
/// with custom parameters.
|
||||
/// </summary>
|
||||
/// <param name="message">The HTTP error message.</param>
|
||||
/// <param name="errorCode">The HTTP error code.</param>
|
||||
/// <param name="target">The HTTP error target.</param>
|
||||
public HttpError(
|
||||
string? message,
|
||||
string? errorCode,
|
||||
string? target)
|
||||
{
|
||||
Error = new ErrorDetails
|
||||
{
|
||||
ErrorCode = errorCode,
|
||||
Message = message,
|
||||
Target = target,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class InternalServerError : ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status500InternalServerError;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public InternalServerError(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
|
||||
public void GatherException(Exception exception)
|
||||
{
|
||||
if (exception is AggregateException)
|
||||
{
|
||||
var agEx = exception as AggregateException;
|
||||
Message = string.Join(" | ", agEx.InnerExceptions.Select(e => e.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = exception.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
using Core.Blueprint.Mongo;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Adapters;
|
||||
|
||||
[CollectionAttributeName("GPSPoints")]
|
||||
public class GPSPointAdapter : Document
|
||||
{
|
||||
[BsonElement("features")]
|
||||
[JsonProperty("features")]
|
||||
public List<FeatureCollection> Features { get; set; } = null!;
|
||||
|
||||
[BsonElement("timestamp")]
|
||||
[JsonProperty("timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
public class FeatureCollection
|
||||
{
|
||||
[BsonElement("type")]
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; } = null!;
|
||||
|
||||
[BsonElement("geometry")]
|
||||
[JsonProperty("geometry")]
|
||||
public Geometry Geometry { get; set; } = null!;
|
||||
|
||||
[BsonElement("properties")]
|
||||
[JsonProperty("properties")]
|
||||
public Properties Properties { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class Properties
|
||||
{
|
||||
[BsonElement("technicianId")]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonProperty("technicianId")]
|
||||
public string TechnicianId { get; set; } = null!;
|
||||
|
||||
[BsonElement("technicianName")]
|
||||
[JsonProperty("technicianName")]
|
||||
public string TechnicianName { get; set; } = null!;
|
||||
|
||||
[BsonElement("sbuSurveyId")]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonProperty("sbuSurveyId")]
|
||||
public string SbuSurveyId { get; set; } = null!;
|
||||
|
||||
[BsonElement("sbuSurveyMapsheetId")]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonProperty("sbuSurveyMapsheetId")]
|
||||
public string SbuSurveyMapsheetId { get; set; } = null!;
|
||||
|
||||
[BsonElement("trailId")]
|
||||
[JsonProperty("trailId")]
|
||||
public string TrailId { get; set; } = null!;
|
||||
|
||||
[BsonElement("deviceSerialNumber")]
|
||||
[JsonProperty("deviceSerialNumber")]
|
||||
public string DeviceSerialNumber { get; set; } = null!;
|
||||
}
|
||||
public class Geometry
|
||||
{
|
||||
[BsonElement("type")]
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; } = null!;
|
||||
|
||||
[BsonElement("coordinates")]
|
||||
[JsonProperty("coordinates")]
|
||||
public List<double> Coordinates { get; set; } = null!;
|
||||
|
||||
[BsonElement("latitude")]
|
||||
[JsonProperty("latitude")]
|
||||
public double Latitude { get; set; }
|
||||
|
||||
[BsonElement("longitude")]
|
||||
[JsonProperty("longitude")]
|
||||
public double Longitude { get; set; }
|
||||
|
||||
[BsonElement("orientation")]
|
||||
[JsonProperty("orientation")]
|
||||
public double Orientation { get; set; }
|
||||
|
||||
[BsonElement("accuracy")]
|
||||
[JsonProperty("accuracy")]
|
||||
public int Accuracy { get; set; }
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Adapters;
|
||||
|
||||
public class GeometryAdapter
|
||||
{
|
||||
[BsonElement("type")]
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; } = null!;
|
||||
|
||||
[BsonElement("coordinates")]
|
||||
[JsonProperty("coordinates")]
|
||||
public List<double> Coordinates { get; set; } = null!;
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
using Core.Blueprint.Mongo;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Adapters;
|
||||
|
||||
[CollectionAttributeName("Mapsheets")]
|
||||
public class MapsheetAdapter : Document
|
||||
{
|
||||
[BsonElement("features")]
|
||||
[JsonProperty("features")]
|
||||
public List<MapsheetCollection>? Features { get; set; }
|
||||
|
||||
[BsonElement("timestamp")]
|
||||
[JsonProperty("timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
public class MapsheetTechnicians
|
||||
{
|
||||
[BsonElement("technicianId")]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonProperty("technicianId")]
|
||||
public string TechnicianId { get; set; } = null!;
|
||||
|
||||
[BsonElement("technicianName")]
|
||||
[JsonProperty("technicianName")]
|
||||
public string TechnicianName { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class MapsheetProperties
|
||||
{
|
||||
[BsonElement("surveyId")]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonProperty("surveyId")]
|
||||
public string SurveyId { get; set; }
|
||||
|
||||
[BsonElement("mapsheetName")]
|
||||
[JsonProperty("mapsheetName")]
|
||||
public string MapsheetName { get; set; } = null!;
|
||||
|
||||
[BsonElement("workOrderNumber")]
|
||||
[JsonProperty("workOrderNumber")]
|
||||
public string WorkOrderNumber { get; set; } = null!;
|
||||
|
||||
[BsonElement("mapsheetStatus")]
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
[JsonProperty("mapsheetStatus")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public MapsheetStatus MapsheetStatus { get; set; }
|
||||
|
||||
[BsonElement("footage")]
|
||||
[JsonProperty("footage")]
|
||||
public int Footage { get; set; }
|
||||
}
|
||||
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum MapsheetStatus
|
||||
{
|
||||
Ready = 1,
|
||||
InProgress = 2,
|
||||
Complete = 3,
|
||||
QaPending = 4,
|
||||
Closed = 5,
|
||||
Reopened = 6
|
||||
}
|
||||
|
||||
public class MapsheetCollection
|
||||
{
|
||||
[BsonElement("type")]
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; } = null!;
|
||||
|
||||
[BsonElement("mapsheetTechnicians")]
|
||||
[JsonProperty("mapsheetTechnicians")]
|
||||
public List<MapsheetTechnicians>? MapsheetTechnicians { get; set; }
|
||||
|
||||
[BsonElement("geometry")]
|
||||
[JsonProperty("geometry")]
|
||||
public List<GeometryAdapter> Geometry { get; set; } = null!;
|
||||
|
||||
[BsonElement("properties")]
|
||||
[JsonProperty("properties")]
|
||||
public MapsheetProperties? Properties { get; set; }
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using Core.Blueprint.Mongo;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks.Adapters;
|
||||
|
||||
[CollectionAttributeName("Surveys")]
|
||||
public class SurveyAdapter : Document
|
||||
{
|
||||
[BsonElement("surveyName")]
|
||||
[JsonPropertyName("surveyName")]
|
||||
public string SurveyName { get; set; } = null!;
|
||||
|
||||
[BsonElement("surveyType")]
|
||||
[JsonPropertyName("surveyType")]
|
||||
public string SurveyType { get; set; } = null!;
|
||||
|
||||
[BsonElement("locations")]
|
||||
[JsonPropertyName("locations")]
|
||||
public List<string> Locations { get; set; } = [];
|
||||
|
||||
[BsonElement("project")]
|
||||
[JsonPropertyName("project")]
|
||||
public string Project { get; set; } = null!;
|
||||
|
||||
[BsonElement("surveyStatus")]
|
||||
[JsonPropertyName("surveyStatus")]
|
||||
public string SurveyStatus { get; set; } = null!;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[DefaultStatusCode(DefaultStatusCode)]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class PreconditionFailedObjectResult : ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status412PreconditionFailed;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public PreconditionFailedObjectResult(object value)
|
||||
: base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[DefaultStatusCode(DefaultStatusCode)]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class ServiceUnavaliableResult : ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status503ServiceUnavailable;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public ServiceUnavaliableResult(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class TimeoutServiceError : ObjectResult
|
||||
{
|
||||
private const int DefaultStatusCode = StatusCodes.Status504GatewayTimeout;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public TimeoutServiceError(object value) : base(value)
|
||||
{
|
||||
StatusCode = DefaultStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public abstract class BasePresenter : IBusinessErrorPort, INoContentPort, INotFoundPort,
|
||||
IValidationErrorPort, ITimeoutPort, IServiceUnavaliablePort, IAcceptedPort, IForbiddenPort,
|
||||
IUnauthorizedPort, IInternalServerErrorPort, IBadRequestPort
|
||||
{
|
||||
public required IActionResult ViewModel { get; set; }
|
||||
|
||||
public void BadRequest(string message)
|
||||
{
|
||||
ViewModel = new BadRequestError(message);
|
||||
}
|
||||
public void BadRequest(object message)
|
||||
{
|
||||
ViewModel = new BadRequestError(message);
|
||||
}
|
||||
public void BusinessError(string errorMessage)
|
||||
{
|
||||
ViewModel = new UnprocessableEntityObjectResult(errorMessage);
|
||||
}
|
||||
|
||||
public void NoContentSuccess()
|
||||
{
|
||||
ViewModel = new NoContentResult();
|
||||
}
|
||||
|
||||
public void NotFound()
|
||||
{
|
||||
ViewModel = new NotFoundResult();
|
||||
}
|
||||
|
||||
public void NotFound(object error)
|
||||
{
|
||||
ViewModel = new NotFoundObjectResult(error);
|
||||
}
|
||||
|
||||
public void ValidationErrors(IEnumerable<Notification> notifications)
|
||||
{
|
||||
ViewModel = new PreconditionFailedObjectResult(notifications);
|
||||
}
|
||||
|
||||
public void TimeoutServiceError()
|
||||
{
|
||||
ViewModel = new TimeoutServiceError("Timeout Error");
|
||||
}
|
||||
|
||||
public void ServiceUnavaiable(string errorMessage)
|
||||
{
|
||||
ViewModel = new ServiceUnavaliableResult(errorMessage);
|
||||
}
|
||||
|
||||
public void Accepted()
|
||||
{
|
||||
ViewModel = new AcceptedResult();
|
||||
}
|
||||
|
||||
public void ValidationError(string argument, string message)
|
||||
{
|
||||
var notification = new Notification(argument, message);
|
||||
ViewModel = new PreconditionFailedObjectResult(notification);
|
||||
}
|
||||
|
||||
public void Unauthorized()
|
||||
{
|
||||
ViewModel = new UnauthorizedResult();
|
||||
}
|
||||
public void Forbidden()
|
||||
{
|
||||
ViewModel = new ForbidResult();
|
||||
}
|
||||
public void Forbidden(string message)
|
||||
{
|
||||
ViewModel = new ForbidResult(message);
|
||||
}
|
||||
|
||||
public void InternalServerError(object message)
|
||||
{
|
||||
ViewModel = new InternalServerError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IAcceptedPort
|
||||
{
|
||||
void Accepted();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IBadRequestPort
|
||||
{
|
||||
void BadRequest(object message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IBasePort
|
||||
{
|
||||
IActionResult ViewModel { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IBusinessErrorPort
|
||||
{
|
||||
void BusinessError(string errorMessage);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface ICreatedPort<in TCommand> where TCommand : class, new()
|
||||
{
|
||||
void Created(TCommand output);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IForbiddenPort
|
||||
{
|
||||
void Forbidden();
|
||||
void Forbidden(string message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IInternalServerErrorPort
|
||||
{
|
||||
void InternalServerError(object message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface INoContentPort
|
||||
{
|
||||
void NoContentSuccess();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface INotFoundPort
|
||||
{
|
||||
void NotFound();
|
||||
void NotFound(object error);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IServiceUnavaliablePort
|
||||
{
|
||||
void ServiceUnavaiable(string errorMessage);
|
||||
}
|
||||
}
|
||||
11
Lib.Architecture.BuildingBlocks/Presentation/ISuccessPort.cs
Normal file
11
Lib.Architecture.BuildingBlocks/Presentation/ISuccessPort.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface ICommandSuccessPort<in TCommand> where TCommand : class, new()
|
||||
{
|
||||
void Success(TCommand output);
|
||||
}
|
||||
public interface IQuerySuccessPort<in TQuery> where TQuery : class, new()
|
||||
{
|
||||
void Success(TQuery output);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface ITimeoutPort
|
||||
{
|
||||
void TimeoutServiceError();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IUnauthorizedPort
|
||||
{
|
||||
void Unauthorized();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IValidationErrorPort
|
||||
{
|
||||
void ValidationError(string argument, string message);
|
||||
void ValidationErrors(IEnumerable<Notification> notifications);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IQueryHandler<in T> where T : IQuery
|
||||
{
|
||||
ValueTask<IQueryResult> ExecuteAsync(T query, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
}
|
||||
9
Lib.Architecture.BuildingBlocks/Queries/IQuery.cs
Normal file
9
Lib.Architecture.BuildingBlocks/Queries/IQuery.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IQuery { bool Validate(); }
|
||||
public interface IQueryResult { }
|
||||
}
|
||||
44
Lib.Architecture.BuildingBlocks/RegisterBuildingBlocks.cs
Normal file
44
Lib.Architecture.BuildingBlocks/RegisterBuildingBlocks.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation.AspNetCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public static class RegisterBuildingBlocks
|
||||
{
|
||||
public static IServiceCollection AddBuildingBlocks(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<ICommandResult, CommandResult>();
|
||||
services.AddScoped<IQueryResult, QueryResult>();
|
||||
|
||||
return services;
|
||||
}
|
||||
public static IServiceCollection AddValidatorsFromNamespace(this IServiceCollection services, Assembly assembly, string @namespace)
|
||||
{
|
||||
var validators = assembly.GetTypes()
|
||||
.Where(t => t.IsClass && !t.IsAbstract && t.IsPublic && t.Namespace == @namespace)
|
||||
.Where(t => typeof(IValidator).IsAssignableFrom(t))
|
||||
.ToList();
|
||||
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
var interfaceType = validator.GetInterfaces()
|
||||
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IValidator<>));
|
||||
|
||||
if (interfaceType != null)
|
||||
{
|
||||
services.AddTransient(interfaceType, validator);
|
||||
}
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Lib.Architecture.BuildingBlocks/Utils/PrivateResolver.cs
Normal file
21
Lib.Architecture.BuildingBlocks/Utils/PrivateResolver.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public class PrivateResolver : DefaultContractResolver
|
||||
{
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
var prop = base.CreateProperty(member, memberSerialization);
|
||||
if (!prop.Writable)
|
||||
{
|
||||
var property = member as PropertyInfo;
|
||||
var hasPrivateSetter = property?.GetSetMethod(true) is not null;
|
||||
prop.Writable = hasPrivateSetter;
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Lib.Architecture.BuildingBlocks/Utils/TypeGetter.cs
Normal file
13
Lib.Architecture.BuildingBlocks/Utils/TypeGetter.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public static class TypeGetter
|
||||
{
|
||||
public static Type? GetTypeFromCurrencDomainAssembly(string typeName)
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes()
|
||||
.Where(x => x.FullName == typeName || x.Name == typeName))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IValidationHandler
|
||||
{
|
||||
bool ExecuteValidation<TV, TE>(TV validationObject, TE command) where TV : AbstractValidator<TE> where TE : Command;
|
||||
}
|
||||
//RuleFor
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface INotifier
|
||||
{
|
||||
IReadOnlyCollection<Notification> Notifications { get; }
|
||||
bool HasNotifications { get; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
using FluentValidation;
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
public interface IValidable
|
||||
{
|
||||
bool IsValid(IValidator validator);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class Notification(string argument, string mensagem)
|
||||
{
|
||||
public string Argument { get; } = argument;
|
||||
public string Message { get; } = mensagem;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
|
||||
namespace Lib.Architecture.BuildingBlocks
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public abstract class Notificator : INotifier, IValidable
|
||||
{
|
||||
public bool HasNotifications => _notifications.Any();
|
||||
|
||||
//Notifications
|
||||
private readonly List<Notification> _notifications = [];
|
||||
public IReadOnlyCollection<Notification> Notifications => _notifications.AsReadOnly();
|
||||
|
||||
protected Notificator()
|
||||
{
|
||||
_notifications = [];
|
||||
}
|
||||
//Validation Results
|
||||
private ValidationResult _validationResult = new();
|
||||
public ValidationResult GetValidationResult() => _validationResult;
|
||||
|
||||
private readonly Dictionary<string, string> _errors = new();
|
||||
|
||||
|
||||
public bool IsValid(IValidator validator)
|
||||
{
|
||||
var context = new ValidationContext<Notificator>(this);
|
||||
|
||||
AddNotification(validator.Validate(context));
|
||||
|
||||
return !HasNotifications;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the entity and adds series of notification to list of errors.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="validator"></param>
|
||||
/// <param name="entity"></param>
|
||||
protected void AddNotification<TEntity>(AbstractValidator<TEntity> validator, TEntity entity) where TEntity : class
|
||||
{
|
||||
_validationResult = validator.Validate(entity);
|
||||
|
||||
if (!_validationResult.IsValid)
|
||||
{
|
||||
foreach (var item in _validationResult.Errors)
|
||||
{
|
||||
_errors.Add(item.ErrorMessage, item.ErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object of validation and Adds Simple Notification to Validation Result
|
||||
/// </summary>
|
||||
/// <param name="validation"></param>
|
||||
private void AddNotification(ValidationResult validation)
|
||||
{
|
||||
if (!validation.IsValid)
|
||||
{
|
||||
foreach (var validationError in validation.Errors)
|
||||
{
|
||||
_notifications.Add(new Notification(
|
||||
validationError.PropertyName,
|
||||
validationError.ErrorMessage
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user