diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..4fd5271
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,3 @@
+{
+ "image": "mcr.microsoft.com/devcontainers/dotnet"
+}
\ No newline at end of file
diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml
index 3aed081..0f2b6ec 100644
--- a/.github/workflows/master.yml
+++ b/.github/workflows/master.yml
@@ -38,9 +38,8 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
- 6.x
- 7.x
8.x
+ 9.x
- name: Build
run: dotnet build -c ${{ env.BUILD_CONFIGURATION }}
@@ -60,9 +59,8 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
- 6.x
- 7.x
8.x
+ 9.x
- uses: dotnet/nbgv@master
with:
diff --git a/Directory.Build.props b/Directory.Build.props
index 2a1e7a6..2190e9e 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -6,7 +6,7 @@
git
true
Latest
- net6.0;net7.0;net8.0
+ net8.0;net9.0
$(FETargetFrameworks)
diff --git a/README.md b/README.md
index 21851bd..b6b1182 100644
--- a/README.md
+++ b/README.md
@@ -291,6 +291,12 @@ The prerelease CI builds are packaged and hosted at [feedz.io](feedz.io), thanks
# Release notes
+## 4.0
+
+- Remove support for .NET 6 and .NET 7
+- Add support for .NET 9
+- Remove dependency on ForEvolve.Core library which means the base exception is now `Exception` instead of `ForEvolve.Exception`.
+
## 3.0
Version 3 of ExceptionMapper is a major rewrite that simplifies the codebase and usage of the library. Here are a few important changes:
diff --git a/samples/WebApi.Minimal/Program.cs b/samples/WebApi.Minimal/Program.cs
index c811bfb..78c8382 100644
--- a/samples/WebApi.Minimal/Program.cs
+++ b/samples/WebApi.Minimal/Program.cs
@@ -9,15 +9,9 @@
var builder = WebApplication.CreateBuilder(args);
#if CHANGE_PROPERTY_NAME_POLICY
-#if NET8_0_OR_GREATER
builder.Services.ConfigureHttpJsonOptions(options => {
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseUpper;
});
-#else
-builder.Services.Configure(options => {
- options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
-});
-#endif
#endif
builder.AddExceptionMapper(builder =>
{
@@ -74,9 +68,7 @@
"---[Others]---",
"/fallback",
"/a-url-that-does-not-exist",
-#if NET7_0_OR_GREATER
"/fluent-validation?name=&description=&range=0",
-#endif
});
app.MapGet("/BadRequestException", context => throw new BadRequestException());
app.MapGet("/ConflictException", context => throw new ConflictException());
@@ -96,7 +88,6 @@
app.MapGet("/MyUnauthorizedException", context => throw new MyUnauthorizedException(Random.Shared.Next(100) % 2 == 0 ? "John" : "Jane"));
app.MapGet("/fallback", context => throw new Exception("An error that gets handled by the fallback handler."));
-#if NET7_0_OR_GREATER
app.MapGet("/fluent-validation", ([AsParameters] Entity entity) =>
{
var validator = new EntityValidator();
@@ -107,7 +98,6 @@
}
return TypedResults.Ok(entity);
});
-#endif
app.Run();
diff --git a/src/ForEvolve.ExceptionMapper/CommonExceptions/ClientErrorException.cs b/src/ForEvolve.ExceptionMapper/CommonExceptions/ClientErrorException.cs
index 8e11789..cef5fc5 100644
--- a/src/ForEvolve.ExceptionMapper/CommonExceptions/ClientErrorException.cs
+++ b/src/ForEvolve.ExceptionMapper/CommonExceptions/ClientErrorException.cs
@@ -4,7 +4,7 @@
/// Client error responses (400 – 499)
///
See also
///
-public abstract class ClientErrorException : ForEvolveException
+public abstract class ClientErrorException : Exception
{
public ClientErrorException()
{
diff --git a/src/ForEvolve.ExceptionMapper/CommonExceptions/ServerErrorException.cs b/src/ForEvolve.ExceptionMapper/CommonExceptions/ServerErrorException.cs
index 4c84abf..9a95824 100644
--- a/src/ForEvolve.ExceptionMapper/CommonExceptions/ServerErrorException.cs
+++ b/src/ForEvolve.ExceptionMapper/CommonExceptions/ServerErrorException.cs
@@ -4,7 +4,7 @@
/// Server error responses (500 – 599)
///
See also
///
-public abstract class ServerErrorException : ForEvolveException
+public abstract class ServerErrorException : Exception
{
public ServerErrorException()
{
diff --git a/src/ForEvolve.ExceptionMapper/DependencyInjection/ServiceCollectionExtensions.cs b/src/ForEvolve.ExceptionMapper/DependencyInjection/ServiceCollectionExtensions.cs
index 3972fe1..775978c 100644
--- a/src/ForEvolve.ExceptionMapper/DependencyInjection/ServiceCollectionExtensions.cs
+++ b/src/ForEvolve.ExceptionMapper/DependencyInjection/ServiceCollectionExtensions.cs
@@ -53,23 +53,16 @@ public static WebApplicationBuilder AddExceptionMapper(this WebApplicationBuilde
private static void AddSerializationHandler(this IServiceCollection services, IConfiguration configuration)
{
-#if NET7_0_OR_GREATER
services.ConfigureHttpJsonOptions(options => {
options.SerializerOptions.DictionaryKeyPolicy = options.SerializerOptions.PropertyNamingPolicy;
});
-#endif
services
.AddOptions()
.Bind(configuration.GetSection("ExceptionMapper:ProblemDetailsSerialization"))
.ValidateOnStart()
;
services.AddSingleton(sp => sp.GetRequiredService>().Value);
-#if NET7_0_OR_GREATER
services.AddProblemDetails();
-#endif
- // Workaround: binding a local copy of the DefaultProblemDetailsFactory because the .NET class is internal.
- // Moreover, the only way to add the class is by calling the AddMvcCore method, which add way more services.
- // So until we can add the DefaultProblemDetailsFactory
services.TryAddSingleton();
services.TryAddSingleton();
}
diff --git a/src/ForEvolve.ExceptionMapper/ForEvolve.ExceptionMapper.csproj b/src/ForEvolve.ExceptionMapper/ForEvolve.ExceptionMapper.csproj
index c9822a9..c15c5ef 100644
--- a/src/ForEvolve.ExceptionMapper/ForEvolve.ExceptionMapper.csproj
+++ b/src/ForEvolve.ExceptionMapper/ForEvolve.ExceptionMapper.csproj
@@ -7,10 +7,13 @@
-
-
-
+
+
+
+
+
+
diff --git a/src/ForEvolve.ExceptionMapper/Serialization/DefaultProblemDetailsFactory.cs b/src/ForEvolve.ExceptionMapper/Serialization/DefaultProblemDetailsFactory.cs
index b61f82f..1629bf3 100644
--- a/src/ForEvolve.ExceptionMapper/Serialization/DefaultProblemDetailsFactory.cs
+++ b/src/ForEvolve.ExceptionMapper/Serialization/DefaultProblemDetailsFactory.cs
@@ -1,4 +1,6 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Load this only for .NET 8.
+#if !NET9_0_OR_GREATER
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Http;
@@ -100,43 +102,4 @@ private void ApplyProblemDetailsDefaults(HttpContext httpContext, ProblemDetails
_configure?.Invoke(new() { HttpContext = httpContext!, ProblemDetails = problemDetails });
}
}
-
-#if NET6_0
-public class ProblemDetailsOptions
-{
- ///
- /// The operation that customizes the current instance.
- ///
- public Action? CustomizeProblemDetails { get; set; }
-}
-
-public class ProblemDetailsContext
-{
- private ProblemDetails? _problemDetails;
-
- ///
- /// The associated with the current request being processed by the filter.
- ///
- public HttpContext? HttpContext { get; init; }
-
- ///
- /// A collection of additional arbitrary metadata associated with the current request endpoint.
- ///
- public EndpointMetadataCollection? AdditionalMetadata { get; init; }
-
- ///
- /// An instance of that will be
- /// used during the response payload generation.
- ///
- public ProblemDetails ProblemDetails
- {
- get => _problemDetails ??= new ProblemDetails();
- set => _problemDetails = value;
- }
-
- ///
- /// The exception causing the problem or null if no exception information is available.
- ///
- public Exception? Exception { get; init; }
-}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationHandler.cs b/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationHandler.cs
index e35b369..7c91d37 100644
--- a/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationHandler.cs
+++ b/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationHandler.cs
@@ -17,15 +17,11 @@ public class ProblemDetailsSerializationHandler : IExceptionSerializer
private readonly ProblemDetailsFactory _problemDetailsFactory;
private readonly IHostEnvironment _hostEnvironment;
private readonly ProblemDetailsSerializationOptions _options;
-#if NET7_0_OR_GREATER
private readonly IProblemDetailsService _problemDetailsService;
-#endif
private readonly JsonSerializerOptions _jsonSerializerOptions;
public ProblemDetailsSerializationHandler(
-#if NET7_0_OR_GREATER
IProblemDetailsService problemDetailsService,
-#endif
ProblemDetailsFactory problemDetailsFactory,
IHostEnvironment hostEnvironment,
ProblemDetailsSerializationOptions options,
@@ -34,9 +30,7 @@ public ProblemDetailsSerializationHandler(
_problemDetailsFactory = problemDetailsFactory ?? throw new ArgumentNullException(nameof(problemDetailsFactory));
_hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment));
_options = options ?? throw new ArgumentNullException(nameof(options));
-#if NET7_0_OR_GREATER
_problemDetailsService = problemDetailsService ?? throw new ArgumentNullException(nameof(problemDetailsService));
-#endif
_jsonSerializerOptions = jsonOptions.Value.SerializerOptions ?? throw new ArgumentNullException(nameof(jsonOptions));
}
@@ -113,27 +107,13 @@ public async Task ExecuteAsync(ExceptionHandlingContext ctx)
}
// Output the problem details
-#if NET7_0_OR_GREATER
var problemDetailsContext = new ProblemDetailsContext
{
HttpContext = ctx.HttpContext,
-#if NET8_0_OR_GREATER
Exception = ctx.Error,
-#endif
ProblemDetails = problemDetails,
};
await _problemDetailsService.WriteAsync(problemDetailsContext);
-#else
-#pragma warning disable CS0618 // Type or member is obsolete
- ctx.HttpContext.Response.ContentType = _options.ContentType;
- await JsonSerializer.SerializeAsync(
- ctx.HttpContext.Response.Body,
- problemDetails,
- _jsonSerializerOptions,
- cancellationToken: ctx.HttpContext.RequestAborted
- );
-#pragma warning restore CS0618 // Type or member is obsolete
-#endif
}
private string FormatName(string name)
diff --git a/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationOptions.cs b/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationOptions.cs
index b9bbd10..f33a9b6 100644
--- a/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationOptions.cs
+++ b/src/ForEvolve.ExceptionMapper/Serialization/Json/ProblemDetailsSerializationOptions.cs
@@ -6,10 +6,4 @@ public class ProblemDetailsSerializationOptions
{
public bool SerializeExceptions { get; set; } = true;
public Func DisplayDebugInformation { get; set; } = (ExceptionHandlingContext ctx) => false;
-#if NET6_0
- private const string _obsoleteMessage = "This property was removed when targeting .NET 7+. The library now leverages the `IProblemDetailsService` interface instead.";
-
- [Obsolete(_obsoleteMessage)]
- public string ContentType { get; set; } = "application/problem+json; charset=utf-8";
-#endif
}
diff --git a/test/ForEvolve.ExceptionMapper.Tests/ExceptionHandlerTest.cs b/test/ForEvolve.ExceptionMapper.Tests/ExceptionHandlerTest.cs
index 9c188ec..2d2db65 100644
--- a/test/ForEvolve.ExceptionMapper.Tests/ExceptionHandlerTest.cs
+++ b/test/ForEvolve.ExceptionMapper.Tests/ExceptionHandlerTest.cs
@@ -60,7 +60,7 @@ await sut.ExecuteAsync(new ExceptionHandlingContext(
Assert.Equal(
sut.StatusCode,
- _httpContextHelper.HttpResponse.StatusCode
+ _httpContextHelper.HttpResponseFake.StatusCode
);
}
diff --git a/test/ForEvolve.ExceptionMapper.Tests/ForEvolve.ExceptionMapper.Tests.csproj b/test/ForEvolve.ExceptionMapper.Tests/ForEvolve.ExceptionMapper.Tests.csproj
index cb9333e..1091a70 100644
--- a/test/ForEvolve.ExceptionMapper.Tests/ForEvolve.ExceptionMapper.Tests.csproj
+++ b/test/ForEvolve.ExceptionMapper.Tests/ForEvolve.ExceptionMapper.Tests.csproj
@@ -12,4 +12,19 @@
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/version.json b/version.json
index 8d459ea..bc85e5f 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "3.0",
+ "version": "4.0",
"publicReleaseRefSpec": [
"^refs/heads/master$"
],