diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31607fa..b9c8d36 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Setup .NET
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: 6.0.x
+ dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
diff --git a/.gitignore b/.gitignore
index dfcfd56..d04cdf4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -348,3 +348,6 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+
+# JetBrains folders
+.idea/*
\ No newline at end of file
diff --git a/Api/Api.csproj b/Api/Api.csproj
index 9424ce0..cd7a723 100644
--- a/Api/Api.csproj
+++ b/Api/Api.csproj
@@ -1,16 +1,17 @@
- net6.0
+ net8.0
enable
true
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/Api/Domain/Company.cs b/Api/Domain/Company.cs
index 23eaa8c..1ae8b2c 100644
--- a/Api/Domain/Company.cs
+++ b/Api/Domain/Company.cs
@@ -1,13 +1,12 @@
-namespace Api.Domain
+namespace Api.Domain;
+
+public class Company
{
- public class Company
- {
- public string Name { get; set; }
+ public string Name { get; set; }
- public string Address { get; set; }
+ public string Address { get; set; }
- public string RegistrationNumber { get; set; }
+ public string RegistrationNumber { get; set; }
- public CompanyStatus CompanyStatus { get; set; }
- }
-}
+ public CompanyStatus CompanyStatus { get; set; }
+}
\ No newline at end of file
diff --git a/Api/Domain/CompanyService.cs b/Api/Domain/CompanyService.cs
index 177b091..b8f5103 100644
--- a/Api/Domain/CompanyService.cs
+++ b/Api/Domain/CompanyService.cs
@@ -1,25 +1,25 @@
using Api.Infrastructure;
-namespace Api.Domain
+namespace Api.Domain;
+
+public class CompanyService : ICompanyService
{
- public class CompanyService : ICompanyService
- {
- private readonly IProxy _proxy;
+ private readonly IProxy _proxy;
- public CompanyService(IProxy proxy)
- {
+ public CompanyService(IProxy proxy)
+ {
_proxy = proxy;
}
- public async Task GetCompanyAsync(string registrationNumber, CancellationToken cancellationToken = default)
- {
+ public async Task GetCompanyAsync(string registrationNumber, CancellationToken cancellationToken = default)
+ {
var company = await _proxy.GetCompanyAsync(registrationNumber, cancellationToken);
CheckEligibilityRules(company);
return company;
}
- private static void CheckEligibilityRules(Company company)
- {
+ private static void CheckEligibilityRules(Company company)
+ {
if (company.CompanyStatus != CompanyStatus.Active)
{
throw DomainException.InvalidCompanyStatus();
@@ -30,5 +30,4 @@ private static void CheckEligibilityRules(Company company)
throw DomainException.InvalidCompanyAddress();
}
}
- }
-}
+}
\ No newline at end of file
diff --git a/Api/Infrastructure/Proxy.cs b/Api/Infrastructure/Proxy.cs
index b83bfa9..b053e82 100644
--- a/Api/Infrastructure/Proxy.cs
+++ b/Api/Infrastructure/Proxy.cs
@@ -1,53 +1,52 @@
using Api.Domain;
-namespace Api.Infrastructure
+namespace Api.Infrastructure;
+
+public class Proxy : IProxy
{
- public class Proxy : IProxy
+ public Task GetCompanyAsync(string registrationNumber, CancellationToken cancellationToken = default)
{
- public Task GetCompanyAsync(string registrationNumber, CancellationToken cancellationToken = default)
- {
- var nextValue = Randomize.Next();
+ var nextValue = Randomize.Next();
- return nextValue switch
+ return nextValue switch
+ {
+ < 300 => Task.FromResult(new Company
{
- < 300 => Task.FromResult(new Company
- {
- Name = Randomize.RandomString(10),
- RegistrationNumber = registrationNumber,
- Address = Randomize.RandomString(20),
- CompanyStatus = CompanyStatus.Active
- }),
- < 400 => Task.FromResult(new Company
- {
- Name = Randomize.RandomString(10),
- RegistrationNumber = registrationNumber,
- Address = Randomize.RandomString(20),
- CompanyStatus = CompanyStatus.Delisted
- }),
- < 600 => Task.FromResult(new Company
- {
- Name = Randomize.RandomString(10),
- RegistrationNumber = registrationNumber,
- CompanyStatus = CompanyStatus.Active
- }),
- < 700 => throw InfrastructureException.PartnerWebServiceIsDown(),
- < 800 => throw InfrastructureException.PartnerWebServiceIsTakingTooLongToRespond(),
- _ => throw InfrastructureException.PartnerWebServiceReceivingTooManyRequests()
- };
- }
+ Name = Randomize.RandomString(10),
+ RegistrationNumber = registrationNumber,
+ Address = Randomize.RandomString(20),
+ CompanyStatus = CompanyStatus.Active
+ }),
+ < 400 => Task.FromResult(new Company
+ {
+ Name = Randomize.RandomString(10),
+ RegistrationNumber = registrationNumber,
+ Address = Randomize.RandomString(20),
+ CompanyStatus = CompanyStatus.Delisted
+ }),
+ < 600 => Task.FromResult(new Company
+ {
+ Name = Randomize.RandomString(10),
+ RegistrationNumber = registrationNumber,
+ CompanyStatus = CompanyStatus.Active
+ }),
+ < 700 => throw InfrastructureException.PartnerWebServiceIsDown(),
+ < 800 => throw InfrastructureException.PartnerWebServiceIsTakingTooLongToRespond(),
+ _ => throw InfrastructureException.PartnerWebServiceReceivingTooManyRequests()
+ };
+ }
- public class Randomize
- {
- private static readonly Random Random = new(Guid.NewGuid().GetHashCode());
+ private sealed class Randomize
+ {
+ private static readonly Random Random = new(Guid.NewGuid().GetHashCode());
- public static int Next() => Random.Next(1, 1000);
+ public static int Next() => Random.Next(1, 1000);
- public static string RandomString(int length)
- {
- const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- return new string(Enumerable.Repeat(chars, length)
- .Select(s => s[Random.Next(s.Length)]).ToArray());
- }
+ public static string RandomString(int length)
+ {
+ const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ return new string(Enumerable.Repeat(chars, length)
+ .Select(s => s[Random.Next(s.Length)]).ToArray());
}
}
-}
+}
\ No newline at end of file
diff --git a/Api/Presentation/Validators/CompanyRequestDtoValidator.cs b/Api/Presentation/Validators/CompanyRequestDtoValidator.cs
index d319a3d..9720153 100644
--- a/Api/Presentation/Validators/CompanyRequestDtoValidator.cs
+++ b/Api/Presentation/Validators/CompanyRequestDtoValidator.cs
@@ -1,16 +1,15 @@
using Api.Presentation.ViewModels;
using FluentValidation;
-namespace Api.Presentation.Validators
+namespace Api.Presentation.Validators;
+
+public class CompanyRequestDtoValidator : AbstractValidator
{
- public class CompanyRequestDtoValidator : AbstractValidator
+ public CompanyRequestDtoValidator()
{
- public CompanyRequestDtoValidator()
- {
RuleFor(x => x.RegistrationNumber)
.NotEmpty()
.MinimumLength(5)
.MaximumLength(10);
}
- }
-}
+}
\ No newline at end of file
diff --git a/Api/Presentation/ViewModels/CompanyResponseDto.cs b/Api/Presentation/ViewModels/CompanyResponseDto.cs
index 90598f2..fe545d2 100644
--- a/Api/Presentation/ViewModels/CompanyResponseDto.cs
+++ b/Api/Presentation/ViewModels/CompanyResponseDto.cs
@@ -1,20 +1,19 @@
using Api.Domain;
-namespace Api.Presentation.ViewModels
+namespace Api.Presentation.ViewModels;
+
+public class CompanyResponseDto
{
- public class CompanyResponseDto
- {
- public string Name { get; set; }
+ public string Name { get; set; }
- public string Address { get; set; }
+ public string Address { get; set; }
- public string RegistrationNumber { get; set; }
+ public string RegistrationNumber { get; set; }
- public CompanyResponseDto(Company company)
- {
+ public CompanyResponseDto(Company company)
+ {
Name = company.Name;
Address = company.Address;
RegistrationNumber = company.RegistrationNumber;
}
- }
-}
+}
\ No newline at end of file
diff --git a/Api/Startup.cs b/Api/Startup.cs
index e53da94..f8ea481 100644
--- a/Api/Startup.cs
+++ b/Api/Startup.cs
@@ -2,67 +2,68 @@
using Api.Infrastructure;
using Api.Presentation.Middlewares;
using Api.Presentation.Validators;
+using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
-namespace Api
+namespace Api;
+
+public class Startup
{
- public class Startup
+ public Startup(IConfiguration configuration)
{
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
+ Configuration = configuration;
+ }
- public IConfiguration Configuration { get; }
+ public IConfiguration Configuration { get; }
- public void ConfigureServices(IServiceCollection services)
- {
- services
- .AddControllers()
- .ConfigureApiBehaviorOptions(options =>
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services
+ .AddControllers()
+ .ConfigureApiBehaviorOptions(options =>
+ {
+ options.InvalidModelStateResponseFactory = context =>
{
- options.InvalidModelStateResponseFactory = context =>
+ var problemDetails = new ValidationProblemDetails(context.ModelState);
+ return new BadRequestObjectResult(problemDetails)
{
- var problemDetails = new ValidationProblemDetails(context.ModelState);
- return new BadRequestObjectResult(problemDetails)
- {
- ContentTypes = { "application/problem+json" }
- };
+ ContentTypes = { "application/problem+json" }
};
- });
+ };
+ });
- services.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining());
+ services.AddFluentValidationAutoValidation();
+ services.AddValidatorsFromAssemblyContaining();
- services.AddEndpointsApiExplorer();
- services.AddSwaggerGen();
+ services.AddEndpointsApiExplorer();
+ services.AddSwaggerGen();
- services.AddScoped();
- services.AddScoped();
- }
+ services.AddScoped();
+ services.AddScoped();
+ }
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
{
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
+ app.UseDeveloperExceptionPage();
+ }
- app.UseExceptionHandlingMiddleware();
+ app.UseExceptionHandlingMiddleware();
- app.UseHttpsRedirection();
+ app.UseHttpsRedirection();
- app.UseRouting();
+ app.UseRouting();
- app.UseAuthorization();
+ app.UseAuthorization();
- app.UseSwagger();
- app.UseSwaggerUI();
+ app.UseSwagger();
+ app.UseSwaggerUI();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ });
}
-}
+}
\ No newline at end of file
diff --git a/ExceptionHandlingMiddlewareDemo.sln b/ExceptionHandlingMiddlewareDemo.sln
index 126493f..4abede4 100644
--- a/ExceptionHandlingMiddlewareDemo.sln
+++ b/ExceptionHandlingMiddlewareDemo.sln
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
.github\workflows\ci.yml = .github\workflows\ci.yml
README.md = README.md
+ global.json = global.json
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{F13C9ADF-5755-4273-94C9-97C197B7CB8C}"
diff --git a/README.md b/README.md
index efa67c1..fce3514 100644
--- a/README.md
+++ b/README.md
@@ -15,4 +15,4 @@ Exceptions are thrown by :
Exceptions are catched by the exception middleware and formatted using [problem details specification](https://datatracker.ietf.org/doc/html/rfc7807)
-**`Tools`** : vs22, net 6.0, xunit
\ No newline at end of file
+**`Tools`** : net 8.0, xunit
\ No newline at end of file
diff --git a/Tests/ExceptionHandlingMiddlewareTests.cs b/Tests/ExceptionHandlingMiddlewareTests.cs
index 6466920..74d31a1 100644
--- a/Tests/ExceptionHandlingMiddlewareTests.cs
+++ b/Tests/ExceptionHandlingMiddlewareTests.cs
@@ -8,43 +8,43 @@
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
-namespace Tests
+namespace Tests;
+
+public class ExceptionHandlingMiddlewareTests
{
- public class ExceptionHandlingMiddlewareTests
+ [Theory]
+ [ClassData(typeof(TestCases))]
+ public async Task Should_Return_Valid_StatusCode(RequestDelegate next, int expectedStatusCode)
{
- [Theory]
- [ClassData(typeof(TestCases))]
- public async Task Should_Return_Valid_StatusCode(RequestDelegate next, int expectedStatusCode)
+ // arrange
+ using var stream = new MemoryStream();
+ var logger = NullLogger.Instance;
+ var context = new DefaultHttpContext
{
- // arrange
- var logger = NullLogger.Instance;
- var context = new DefaultHttpContext
+ Response =
{
- Response =
- {
- Body = new MemoryStream()
- }
- };
- var middleware = new ExceptionHandlingMiddleware(next, logger);
+ Body = stream
+ }
+ };
+ var middleware = new ExceptionHandlingMiddleware(next, logger);
- // act
- await middleware.Invoke(context);
+ // act
+ await middleware.Invoke(context);
- // assert
- context.Response.StatusCode.Should().Be(expectedStatusCode);
- }
+ // assert
+ context.Response.StatusCode.Should().Be(expectedStatusCode);
+ }
- private class TestCases : TheoryData
+ private class TestCases : TheoryData
+ {
+ public TestCases()
{
- public TestCases()
- {
- Add(_ => Task.CompletedTask, 200);
- Add(_ => throw DomainException.InvalidCompanyStatus(), 501);
- Add(_ => throw DomainException.InvalidCompanyAddress(), 501);
- Add(_ => throw InfrastructureException.PartnerWebServiceIsDown(), 503);
- Add(_ => throw InfrastructureException.PartnerWebServiceIsTakingTooLongToRespond(), 503);
- Add(_ => throw InfrastructureException.PartnerWebServiceReceivingTooManyRequests(), 503);
- }
+ Add(_ => Task.CompletedTask, 200);
+ Add(_ => throw DomainException.InvalidCompanyStatus(), 501);
+ Add(_ => throw DomainException.InvalidCompanyAddress(), 501);
+ Add(_ => throw InfrastructureException.PartnerWebServiceIsDown(), 503);
+ Add(_ => throw InfrastructureException.PartnerWebServiceIsTakingTooLongToRespond(), 503);
+ Add(_ => throw InfrastructureException.PartnerWebServiceReceivingTooManyRequests(), 503);
}
}
}
\ No newline at end of file
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 6dc171e..3f17ce7 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -1,21 +1,20 @@
- net6.0
+ net8.0
enable
-
false
-
-
-
-
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..b5b37b6
--- /dev/null
+++ b/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "8.0.0",
+ "rollForward": "latestMajor",
+ "allowPrerelease": false
+ }
+}
\ No newline at end of file