Skip to content

Commit

Permalink
Validate and update for use with AspNetCore 5.0 #68 (#71)
Browse files Browse the repository at this point in the history
* Multi-target netcoreapp3.1 and net5.0 frameworks
* Fix warnings
* Remove global.json for multiple target frameworks
  • Loading branch information
petervandenhout authored Dec 14, 2020
1 parent 01ec7d6 commit a94f17f
Show file tree
Hide file tree
Showing 27 changed files with 169 additions and 79 deletions.
7 changes: 7 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ steps:
packageType: 'sdk'
version: '3.1.200'

# https://dotnet.microsoft.com/download/dotnet/5.0
- task: UseDotNet@2
displayName: Install .Net Core 5.0.101
inputs:
packageType: 'sdk'
version: '5.0.101'

- task: DotNetCoreCLI@2
displayName: Build
inputs:
Expand Down
5 changes: 0 additions & 5 deletions global.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using System;

namespace Opw.HttpExceptions.AspNetCore.Sample.CustomErrors
{
Expand All @@ -13,6 +14,8 @@ public class CustomErrorResult : ObjectResult

public CustomErrorResult(CustomError customError) : base(customError)
{
_ = customError ?? throw new ArgumentNullException(nameof(customError));

StatusCode = customError.Status;
DeclaredType = customError.GetType();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Opw.HttpExceptions.AspNetCore\Opw.HttpExceptions.AspNetCore.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Opw.HttpExceptions.AspNetCore\Opw.HttpExceptions.AspNetCore.csproj" />
</ItemGroup>

</Project>
3 changes: 2 additions & 1 deletion samples/Opw.HttpExceptions.AspNetCore.Sample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public void ConfigureServices(IServiceCollection services)
// This is a simplified version of the default behavior; only map exceptions for 4xx and 5xx responses.
options.IsExceptionResponse = context => (context.Response.StatusCode >= 400 && context.Response.StatusCode < 600);
// Only log the when it has a status code of 500 or higher, or when it not is a HttpException.
options.ShouldLogException = exception => {
options.ShouldLogException = exception =>
{
if ((exception is HttpExceptionBase httpException && (int)httpException.StatusCode >= 500) || !(exception is HttpExceptionBase))
return true;
return false;
Expand Down
2 changes: 2 additions & 0 deletions src/Opw.HttpExceptions.AspNetCore/HttpExceptionsMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public HttpExceptionsMiddleware(
/// </summary>
public async Task Invoke(HttpContext context)
{
_ = context ?? throw new ArgumentNullException(nameof(context));

try
{
await _next(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public static void ExceptionMapper<TException, TExceptionMapper>(this HttpExcept
where TException : Exception
where TExceptionMapper : IExceptionMapper
{
_ = options ?? throw new ArgumentNullException(nameof(options));

if (options.ExceptionMapperDescriptors.ContainsKey(typeof(TException)))
{
options.ExceptionMapperDescriptors[typeof(TException)] = new ExceptionMapperDescriptor
Expand Down Expand Up @@ -46,6 +48,8 @@ public static void ExceptionMapper<TException, TExceptionMapper>(this HttpExcept
public static void HttpResponseMapper<THttpResponseMapper>(this HttpExceptionsOptions options, int status = int.MinValue, params object[] arguments)
where THttpResponseMapper : IHttpResponseMapper
{
_ = options ?? throw new ArgumentNullException(nameof(options));

if (options.HttpResponseMapperDescriptors.ContainsKey(status))
{
options.HttpResponseMapperDescriptors[status] = new HttpResponseMapperDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public HttpExceptionsOptionsSetup(IServiceProvider serviceProvider)
/// <param name="options">The options instance to configure.</param>
public void Configure(HttpExceptionsOptions options)
{
_ = options ?? throw new ArgumentNullException(nameof(options));

if (options.IncludeExceptionDetails == null)
options.IncludeExceptionDetails = IncludeExceptionDetails;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public virtual bool CanMap(Type type)
/// <param name="actionResult">A representation of the exception as a ProblemDetailsResult.</param>
public virtual bool TryMap(Exception exception, HttpContext context, out IStatusCodeActionResult actionResult)
{
_ = exception ?? throw new ArgumentNullException(nameof(exception));

actionResult = default;

if (!CanMap(exception.GetType()))
Expand Down Expand Up @@ -108,6 +110,9 @@ public virtual IStatusCodeActionResult Map(Exception exception, HttpContext cont
/// <returns>Returns either the request path, the exception help link or null.</returns>
protected virtual string MapInstance(TException exception, HttpContext context)
{
_ = exception ?? throw new ArgumentNullException(nameof(exception));
_ = context ?? throw new ArgumentNullException(nameof(context));

if (Options.Value.ExceptionInstanceMapping != null)
{
string instance = Options.Value.ExceptionInstanceMapping(exception);
Expand Down Expand Up @@ -157,6 +162,9 @@ protected virtual int MapStatus(TException exception, HttpContext context)
/// <returns>Returns the Exception type name without the "Exception" suffix.</returns>
protected virtual string MapTitle(TException exception, HttpContext context)
{
_ = exception ?? throw new ArgumentNullException(nameof(exception));
_ = context ?? throw new ArgumentNullException(nameof(context));

string name = null;

if (Options.Value.ExceptionTitleMapping != null)
Expand All @@ -182,6 +190,8 @@ protected virtual string MapTitle(TException exception, HttpContext context)
/// <returns>Returns the Exception message.</returns>
protected virtual string MapDetail(TException exception, HttpContext context)
{
_ = exception ?? throw new ArgumentNullException(nameof(exception));

if (Options.Value.ExceptionDetailMapping != null)
{
string detail = Options.Value.ExceptionDetailMapping(exception);
Expand All @@ -200,6 +210,9 @@ protected virtual string MapDetail(TException exception, HttpContext context)
/// <returns>Returns the Exception.HelpLink or an URI with the Exception type name ("error:[Type:slug]").</returns>
protected virtual string MapType(TException exception, HttpContext context)
{
_ = exception ?? throw new ArgumentNullException(nameof(exception));
_ = context ?? throw new ArgumentNullException(nameof(context));

Uri uri = null;

if (Options.Value.ExceptionTypeMapping != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public bool CanMap(int status)
/// <param name="actionResult">A representation of the HTTP response error as a ProblemDetailsResult.</param>
public bool TryMap(HttpResponse response, out IStatusCodeActionResult actionResult)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

actionResult = default;

if (!CanMap(response.StatusCode))
Expand All @@ -69,6 +71,8 @@ public bool TryMap(HttpResponse response, out IStatusCodeActionResult actionResu
/// <returns>A representation of the response error as a ProblemDetailsResult.</returns>
public IStatusCodeActionResult Map(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

if (!CanMap(response.StatusCode))
throw new ArgumentOutOfRangeException(nameof(response), response, $"HttpResponse status is not {Status}.");

Expand All @@ -91,6 +95,8 @@ public IStatusCodeActionResult Map(HttpResponse response)
/// <returns>Returns the request path, or null.</returns>
protected virtual string MapInstance(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

if (Options.Value.HttpContextInstanceMapping != null)
{
string instance = Options.Value.HttpContextInstanceMapping(response.HttpContext);
Expand All @@ -111,6 +117,8 @@ protected virtual string MapInstance(HttpResponse response)
/// <returns>Returns the status of the response.</returns>
protected virtual int MapStatus(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

if (Options.Value.HttpContextStatusMapping != null)
{
int? status = Options.Value.HttpContextStatusMapping(response.HttpContext);
Expand All @@ -128,6 +136,8 @@ protected virtual int MapStatus(HttpResponse response)
/// <returns>Returns the HTTP status name or the status code.</returns>
protected virtual string MapTitle(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

string status = null;

if (Options.Value.HttpContextTitleMapping != null)
Expand All @@ -154,6 +164,8 @@ protected virtual string MapTitle(HttpResponse response)
/// <returns>Returns the HTTP status name or the status code.</returns>
protected virtual string MapDetail(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

if (Options.Value.HttpContextDetailMapping != null)
{
string detail = Options.Value.HttpContextDetailMapping(response.HttpContext);
Expand All @@ -171,6 +183,8 @@ protected virtual string MapDetail(HttpResponse response)
/// <returns>Returns a status code information link (https://tools.ietf.org/html/rfc7231) or the URI with the HTTP status name ("error:[status:slug]").</returns>
protected virtual string MapType(HttpResponse response)
{
_ = response ?? throw new ArgumentNullException(nameof(response));

Uri uri = null;

if (Options.Value.HttpContextTypeMapping != null)
Expand Down
4 changes: 4 additions & 0 deletions src/Opw.HttpExceptions.AspNetCore/MvcBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public static class MvcBuilderExtensions
/// <param name="configureOptions">An action used to configure the provided options.</param>
public static IMvcCoreBuilder AddHttpExceptions(this IMvcCoreBuilder builder, Action<HttpExceptionsOptions> configureOptions = null)
{
_ = builder ?? throw new ArgumentNullException(nameof(builder));

builder.Services.AddHttpExceptions(configureOptions);

var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<HttpExceptionsOptions>>();
Expand All @@ -32,6 +34,8 @@ public static IMvcCoreBuilder AddHttpExceptions(this IMvcCoreBuilder builder, Ac
/// <param name="configureOptions">An action used to configure the provided options.</param>
public static IMvcBuilder AddHttpExceptions(this IMvcBuilder builder, Action<HttpExceptionsOptions> configureOptions = null)
{
_ = builder ?? throw new ArgumentNullException(nameof(builder));

builder.Services.AddHttpExceptions(configureOptions);

var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<HttpExceptionsOptions>>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
<RootNamespace>Opw.HttpExceptions.AspNetCore</RootNamespace>
<Description>Middleware and extensions for returning exceptions over HTTP, e.g. as ASP.NET Core Problem Details (RFC7807).</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down
7 changes: 5 additions & 2 deletions src/Opw.HttpExceptions.AspNetCore/ProblemDetailsExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Opw.HttpExceptions.AspNetCore.Serialization;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;

namespace Opw.HttpExceptions.AspNetCore
Expand All @@ -19,6 +18,8 @@ public static class ProblemDetailsExtensions
/// <returns>true if the ProblemDetails contains an exception; otherwise, false.</returns>
public static bool TryGetExceptionDetails(this ProblemDetails problemDetails, out SerializableException exception)
{
_ = problemDetails ?? throw new ArgumentNullException(nameof(problemDetails));

if (problemDetails.Extensions.TryGetValue(nameof(ProblemDetailsExtensionMembers.ExceptionDetails).ToCamelCase(), out var value))
return value.TryParseSerializableException(out exception);

Expand Down Expand Up @@ -56,6 +57,8 @@ public static bool TryParseSerializableException(this object value, out Serializ
/// <returns>true if the ProblemDetails contains errors dictionary; otherwise, false.</returns>
public static bool TryGetErrors(this ProblemDetails problemDetails, out IDictionary<string, object[]> errors)
{
_ = problemDetails ?? throw new ArgumentNullException(nameof(problemDetails));

if (problemDetails.Extensions.TryGetValue(nameof(ProblemDetailsExtensionMembers.Errors).ToCamelCase(), out var value))
return value.TryParseErrors(out errors);

Expand Down
3 changes: 3 additions & 0 deletions src/Opw.HttpExceptions.AspNetCore/ProblemDetailsResult.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using System;

namespace Opw.HttpExceptions.AspNetCore
{
Expand All @@ -23,6 +24,8 @@ public class ProblemDetailsResult : ObjectResult
/// <param name="problemDetails">The ProblemDetails</param>
public ProblemDetailsResult(ProblemDetails problemDetails) : base(problemDetails)
{
_ = problemDetails ?? throw new ArgumentNullException(nameof(problemDetails));

StatusCode = problemDetails.Status;
DeclaredType = problemDetails.GetType();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public override SerializableException Read(ref Utf8JsonReader reader, Type typeT

while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
ReadValue(ref reader, serializableException, options);
ReadValue(ref reader, serializableException);
}

if (reader.TokenType != JsonTokenType.EndObject)
Expand All @@ -42,7 +42,7 @@ public override void Write(Utf8JsonWriter writer, SerializableException value, J
throw new NotImplementedException();
}

internal static void ReadValue(ref Utf8JsonReader reader, SerializableException value, JsonSerializerOptions options)
internal static void ReadValue(ref Utf8JsonReader reader, SerializableException value)
{
if (TryReadStringProperty(ref reader, Type, out var propertyValue))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using FluentAssertions;
using Opw.HttpExceptions.AspNetCore._Test;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
Expand All @@ -14,6 +15,8 @@ public class DefaultApiBehaviorTests : IClassFixture<TestWebApplicationFactory<D

public DefaultApiBehaviorTests(TestWebApplicationFactory<DefaultApiBehaviorStartup> factory)
{
_ = factory ?? throw new ArgumentNullException(nameof(factory));

_client = factory.CreateClient();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<IsPackable>false</IsPackable>
<RootNamespace>Opw.HttpExceptions.AspNetCore</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<RootNamespace>Opw.HttpExceptions.AspNetCore</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.9.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.9.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Opw.HttpExceptions.AspNetCore\Opw.HttpExceptions.AspNetCore.csproj" />
<ProjectReference Include="..\Opw.HttpExceptions.AspNetCore.Tests\Opw.HttpExceptions.AspNetCore.Tests.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.1" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Opw.HttpExceptions.AspNetCore\Opw.HttpExceptions.AspNetCore.csproj" />
<ProjectReference Include="..\Opw.HttpExceptions.AspNetCore.Tests\Opw.HttpExceptions.AspNetCore.Tests.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit a94f17f

Please sign in to comment.