Skip to content

Commit d03820a

Browse files
authored
Merge pull request #25 from NiceOneFox/develop
Sprint 2
2 parents b67b392 + b68e618 commit d03820a

40 files changed

+508
-68
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,20 @@ Input parameters:
2222
* Amount of requests
2323
* Modeling time (max time)
2424
* SimulationType (Type of buffer modeling, FIFO, LIFO etc.)
25-
* Lambda (amount of flow) parameter for Poissonian flow
25+
* Lambda for devices (amount of flow) parameter for Poissonian flow
26+
* Lambda for sources
2627

2728
## Technologies
2829
- ASP .NET 6
2930
- C# 10
3031
- AutoMapper
32+
- FluentValidation
33+
- CORS
34+
- NLog
35+
36+
### For testing
37+
- NUnit
38+
- Moq
3139

3240
## Architecture
3341
N-Layer Web API

backend/ServiceSimulation/Api/Api.csproj

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@
88

99
<ItemGroup>
1010
<PackageReference Include="AutoMapper" Version="11.0.1" />
11-
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.0" />
11+
<PackageReference Include="FluentValidation" Version="10.4.0" />
12+
<PackageReference Include="FluentValidation.AspNetCore" Version="10.4.0" />
13+
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="10.4.0" />
14+
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
15+
<PackageReference Include="NLog" Version="4.7.15" />
16+
<PackageReference Include="NLog.Schema" Version="4.7.15" />
17+
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
18+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
1219
</ItemGroup>
1320

1421
<ItemGroup>

backend/ServiceSimulation/Api/Configuration/ApiMapperConfigurator.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Api.Entities;
22
using AutoMapper;
3-
using Bll.Domain.Entities;
3+
using Bll.Domain.Models;
44
using Bll.Domain.Interfaces;
55

66
namespace Api.Configuration;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Microsoft.AspNetCore.Cors.Infrastructure;
2+
3+
namespace Api.Configuration;
4+
5+
public static class CorsPolicies
6+
{
7+
public static readonly (string Name, Action<CorsPolicyBuilder> ConfigurePolicy) AllowRemoteFrontendWithCredentials =
8+
(
9+
"AllowRemoteFrontendWithCredentials",
10+
builder =>
11+
{
12+
var host = Environment.GetEnvironmentVariable("REMOTE_FRONTEND_HOST");
13+
var port = Environment.GetEnvironmentVariable("REMOTE_FRONTEND_PORT");
14+
var scheme = Environment.GetEnvironmentVariable("REMOTE_FRONTEND_SCHEME");
15+
var origin = $"{scheme}://{host}:{port}";
16+
builder
17+
.WithOrigins(origin)
18+
.AllowAnyHeader()
19+
.AllowAnyMethod()
20+
.AllowCredentials();
21+
}
22+
);
23+
}

backend/ServiceSimulation/Api/Controllers/Simulation.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using Api.Entities;
2-
using Api.enums;
2+
using Api.Validation;
33
using AutoMapper;
4-
using Bll.Domain.Entities;
54
using Bll.Domain.Interfaces;
5+
using Bll.Domain.Models;
6+
using FluentValidation;
67
using Microsoft.AspNetCore.Mvc;
78

89
namespace Api.Controllers;
@@ -31,6 +32,8 @@ public Simulation(ISimulationService simulationService,
3132
[HttpGet("/start")]
3233
public IActionResult Start(InputParameters parameters)
3334
{
35+
new InputParametersValidator().ValidateAndThrow(parameters);
36+
3437
_simulationService.StartSimulation(parameters);
3538
var endResultsOfModeling = _resultManager.CalculateResultsOfModeling();
3639
var apiResults = _mapper.Map<ApiResults>((endResultsOfModeling, _results));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Microsoft.AspNetCore.Cors.Infrastructure;
2+
3+
namespace Api.Extensions;
4+
5+
public static class CorsOptionsExtensions
6+
{
7+
public static void AddPolicy(this CorsOptions options, (string Name, Action<CorsPolicyBuilder> ConfigurePolicy) arg)
8+
{
9+
options.AddPolicy(arg.Name, arg.ConfigurePolicy);
10+
}
11+
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Api.Middlewares;
2+
3+
namespace Api.Extensions
4+
{
5+
public static class CustomExceptionHandlerMiddlewareExtensions
6+
{
7+
public static IApplicationBuilder UseCustomExceptionHandler(this IApplicationBuilder builder)
8+
{
9+
return builder.UseMiddleware<CustomExceptionHandlerMiddleware>();
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Net;
2+
using System.Text.Json;
3+
using FluentValidation;
4+
5+
namespace Api.Middlewares
6+
{
7+
public class CustomExceptionHandlerMiddleware
8+
{
9+
private readonly RequestDelegate _next;
10+
11+
private readonly ILogger _logger;
12+
public CustomExceptionHandlerMiddleware(RequestDelegate next,
13+
ILogger<CustomExceptionHandlerMiddleware> logger)
14+
{
15+
_next = next;
16+
_logger = logger;
17+
}
18+
19+
public async Task Invoke(HttpContext context)
20+
{
21+
try
22+
{
23+
await _next(context);
24+
}
25+
catch (Exception ex)
26+
{
27+
await HandleExceptionAsync(context, ex);
28+
}
29+
}
30+
31+
private Task HandleExceptionAsync(HttpContext context, Exception ex)
32+
{
33+
var statusCode = HttpStatusCode.InternalServerError;
34+
var result = string.Empty;
35+
36+
switch (ex)
37+
{
38+
case ValidationException validationException:
39+
statusCode = HttpStatusCode.BadRequest;
40+
result = JsonSerializer.Serialize(validationException.Errors);
41+
_logger.LogDebug(validationException.Message);
42+
break;
43+
44+
default:
45+
statusCode = HttpStatusCode.NotFound;
46+
break;
47+
48+
}
49+
context.Response.ContentType = "application/json";
50+
context.Response.StatusCode = (int)statusCode;
51+
52+
if (result == string.Empty)
53+
{
54+
result = JsonSerializer.Serialize(new { error = ex.Message });
55+
}
56+
return context.Response.WriteAsync(result);
57+
}
58+
}
59+
}

backend/ServiceSimulation/Api/Program.cs

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,57 @@
11
using Api.Configuration;
2+
using Api.Extensions;
3+
using Api.Validation;
24
using Bll.Domain.Entities;
35
using Bll.Domain.Factories;
46
using Bll.Domain.Interfaces;
7+
using Bll.Domain.Models;
58
using Bll.Domain.Services;
9+
using FluentValidation;
10+
using FluentValidation.AspNetCore;
11+
using NLog.Web;
612

713
var builder = WebApplication.CreateBuilder(args);
814

9-
builder.Services.AddControllers();
15+
builder.Services.AddControllers().AddFluentValidation(fv =>
16+
{
17+
fv.RegisterValidatorsFromAssemblyContaining<InputParametersValidator>();
18+
});
19+
20+
#region Logger
21+
builder.Logging.ClearProviders();
22+
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
23+
builder.Host.UseNLog();
24+
#endregion
1025
builder.Services.AddEndpointsApiExplorer();
1126
builder.Services.AddSwaggerGen();
1227

1328
#region servicesDI
1429
builder.Services.AddTransient<ISimulationService, SimulationService>();
1530

1631
builder.Services.AddScoped<ITimeProvider, TimeProvider>();
32+
builder.Services.AddScoped<IFlowProvider, PoissonianFlowProvider>();
33+
1734
builder.Services.AddScoped<IResults, Bll.Domain.Entities.Results>();
1835
builder.Services.AddScoped<IResultManager, ResultManager>();
19-
builder.Services.AddScoped<IResultManager, ResultManager>();
20-
//builder.Services.AddTransient<IBufferManager, StandardBufferManager>();
36+
2137
builder.Services.AddTransient<IBufferManagerFactory, BufferManagerFactory>();
2238
builder.Services.AddTransient<IDeviceManager, DeviceManager>();
2339
builder.Services.AddTransient<ISourceManager, SourceManager>();
24-
//builder.Services.AddScoped<StandardBufferManager>()
25-
// .AddScoped<IBufferManager, StandardBufferManager>(s => s.GetRequiredService<StandardBufferManager>());
2640

27-
//builder.Services.AddScoped<IBufferManager>(s =>
28-
// ActivatorUtilities.CreateInstance<StandardBufferManager>(s));
41+
builder.Services.AddTransient<IValidator<InputParameters>, InputParametersValidator>();
2942
#endregion
3043

44+
#region Mapper
3145
builder.Services.AddMapper();
46+
#endregion
47+
48+
#region CORS
49+
builder.Services.AddCors(opts =>
50+
{
51+
opts.AddPolicy(CorsPolicies.AllowRemoteFrontendWithCredentials);
52+
});
53+
#endregion
54+
3255

3356
var app = builder.Build();
3457

@@ -38,6 +61,8 @@
3861
app.UseSwaggerUI();
3962
}
4063

64+
app.UseCustomExceptionHandler();
65+
4166
app.UseHttpsRedirection();
4267

4368
app.UseAuthorization();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using FluentValidation;
2+
using Bll.Domain.Models;
3+
using Api.enums;
4+
5+
namespace Api.Validation
6+
{
7+
public class InputParametersValidator : AbstractValidator<InputParameters>
8+
{
9+
public InputParametersValidator()
10+
{
11+
RuleFor(p => p.NumberOfSources).NotEmpty().InclusiveBetween(1, 100);
12+
RuleFor(p => p.NumberOfDevices).NotEmpty().InclusiveBetween(1, 100);
13+
RuleFor(p => p.AmountOfRequests).NotEmpty().InclusiveBetween(1, 5000);
14+
RuleFor(p => p.BufferSize).NotEmpty().InclusiveBetween(1, 100);
15+
RuleFor(p => p.LambdaForDevice).NotEmpty().ExclusiveBetween(0, 10000);
16+
RuleFor(p => p.NumberOfSources).NotEmpty().ExclusiveBetween(0, 10000);
17+
RuleFor(p => p.ModelingTime).NotEmpty().ExclusiveBetween(0, 10000);
18+
RuleFor(p => p.BufferType).IsInEnum();
19+
}
20+
}
21+
}

backend/ServiceSimulation/Api/appsettings.Development.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@
44
"Default": "Information",
55
"Microsoft.AspNetCore": "Warning"
66
}
7-
}
7+
},
8+
9+
"REMOTE_FRONTEND_SCHEME": "https",
10+
"REMOTE_FRONTEND_HOST": "localhost",
11+
"REMOTE_FRONTEND_PORT": "8081",
12+
"DISABLE_SSL_SERVER_CERTIFICATES_VALIDATION": "true"
813
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
{
22
"Logging": {
33
"LogLevel": {
4-
"Default": "Information",
5-
"Microsoft.AspNetCore": "Warning"
4+
"Default": "Trace",
5+
"Microsoft": "Warning",
6+
"Microsoft.Hosting.Lifetime": "Information"
67
}
78
},
89
"AllowedHosts": "*"
9-
}
10+
}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
autoReload="true"
5+
internalLogLevel="Info"
6+
internalLogFile="c:\temp\internal-nlog-AspNetCore.txt">
7+
8+
<!-- enable asp.net core layout renderers -->
9+
<extensions>
10+
<add assembly="NLog.Web.AspNetCore"/>
11+
</extensions>
12+
13+
<!-- the targets to write to -->
14+
<targets>
15+
<!-- File Target for all log messages with basic details -->
16+
<target xsi:type="File" name="allfile" fileName="c:\temp\nlog-AspNetCore-all-${shortdate}.log"
17+
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />
18+
19+
<!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
20+
<target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-AspNetCore-own-${shortdate}.log"
21+
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" />
22+
23+
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
24+
<target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" />
25+
</targets>
26+
27+
<!-- rules to map from logger name to target -->
28+
<rules>
29+
<!--All logs, including from Microsoft-->
30+
<logger name="*" minlevel="Trace" writeTo="allfile" />
31+
32+
<!--Output hosting lifetime messages to console target for faster startup detection -->
33+
<logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" />
34+
35+
<!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
36+
<logger name="Microsoft.*" maxlevel="Info" final="true" />
37+
<logger name="System.Net.Http.*" maxlevel="Info" final="true" />
38+
39+
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
40+
</rules>
41+
</nlog>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
12+
<PackageReference Include="Moq" Version="4.17.2" />
13+
<PackageReference Include="NUnit" Version="3.13.2" />
14+
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
15+
<PackageReference Include="coverlet.collector" Version="3.1.0" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\Bll.Domain\Bll.Domain.csproj" />
20+
</ItemGroup>
21+
22+
</Project>

0 commit comments

Comments
 (0)