Skip to content

Commit

Permalink
Merge pull request #25 from JosephWoodward/HttpStatusOverload
Browse files Browse the repository at this point in the history
Add HttpStatus overloads, tidy up overloads and update test names
  • Loading branch information
josephwoodward committed Sep 20, 2018
2 parents cbc0efe + 0f5674d commit 656f187
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 24 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ If talking to a remote service, you could optionally choose to forward the statu
app.UseGlobalExceptionHandler(x =>
{
x.ContentType = "application/json";
x.Map<HttpServiceException>().ToStatusCode(ex => ex.StatusCode).WithBody((e, c) => "Something went wrong");
x.Map<HttpNotFoundException>().ToStatusCode(ex => ex.StatusCode).WithBody((e, c) => "Resource could not be found");
...
});
```
Expand All @@ -123,7 +123,7 @@ app.UseGlobalExceptionHandler(x => {

x.Map<RecordNotFoundException>().ToStatusCode(StatusCodes.Status404NotFound)
.WithBody((ex, context) => JsonConvert.SerializeObject(new {
Message = "Record could not be found"
Message = "Resource could not be found"
}));
});
```
Expand All @@ -134,7 +134,7 @@ Response:
HTTP/1.1 404 Not Found
...
{
"Message": "Record could not be found"
"Message": "Resource could not be found"
}
```

Expand Down Expand Up @@ -182,7 +182,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
});
});

app.Map("/error", x => x.Run(y => throw new RecordNotFoundException("Record could not be found")));
app.Map("/error", x => x.Run(y => throw new RecordNotFoundException("Resource could not be found")));
}
```

Expand All @@ -209,7 +209,7 @@ Expires: -1
<ErrorResponse
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Message>Record could not be found</Message>
<Message>Resource could not be found</Message>
</ErrorResponse>
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<PackageId>GlobalExceptionHandler.ContentNegotiation.Mvc</PackageId>
<PackageTags>global exception handler;asp.net core;.net core</PackageTags>
<title>Content negotiation for GlobalExceptionHandlerDotNet when using ASP.NET Core MVC</title>
<VersionPrefix>2.0.0-beta1</VersionPrefix>
<PackageReleaseNotes>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet/releases/tag/4.0.0-beta</PackageReleaseNotes>
<VersionPrefix>2.0.0-beta2</VersionPrefix>
<PackageReleaseNotes>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet/releases/tag/4.0.0-beta2</PackageReleaseNotes>
<Authors>Joseph Woodward</Authors>
<Description>Enable content negotiation for GlobalExceptionHandlerDotNet when using ASP.NET Core MVC</Description>
<PackageProjectUrl>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Net;

namespace GlobalExceptionHandler.Tests.Exceptions
{
public class HttpNotFoundException : Exception
{
public HttpNotFoundException()
{
}

public HttpNotFoundException(string message) : base(message)
{
}

public HttpNotFoundException(string message, Exception inner) : base(message, inner)
{
}

public HttpStatusCode StatusCodeEnum => HttpStatusCode.NotFound;

public int StatusCodeInt => 404;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Net;

namespace GlobalExceptionHandler.Tests.Exceptions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using GlobalExceptionHandler.Tests.Exceptions;
using GlobalExceptionHandler.Tests.Fixtures;
using GlobalExceptionHandler.WebApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;

namespace GlobalExceptionHandler.Tests.WebApi.StatusCodeTests
{
public class StatusCodeAtRunTimeWithEnum : IClassFixture<WebApiServerFixture>
{
private const string ApiProductNotFound = "/api/productnotfound";
private readonly HttpClient _client;

public StatusCodeAtRunTimeWithEnum(WebApiServerFixture fixture)
{
// Arrange
var webHost = fixture.CreateWebHostWithMvc();
webHost.Configure(app =>
{
app.UseGlobalExceptionHandler(x =>
{
x.ContentType = "application/json";
x.Map<HttpNotFoundException>().ToStatusCode(ex => ex.StatusCodeEnum);
x.ResponseBody(c => JsonConvert.SerializeObject(new TestResponse
{
Message = c.Message
}));
});
app.Map(ApiProductNotFound, config => { config.Run(context => throw new HttpNotFoundException("Record not found")); });
});

_client = new TestServer(webHost).CreateClient();
}

[Fact]
public async Task Returns_correct_response_type()
{
var response = await _client.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), ApiProductNotFound));
response.Content.Headers.ContentType.MediaType.ShouldBe("application/json");
}

[Fact]
public async Task Returns_correct_status_code()
{
var response = await _client.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), ApiProductNotFound));
response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using GlobalExceptionHandler.Tests.Exceptions;
using GlobalExceptionHandler.Tests.Fixtures;
using GlobalExceptionHandler.WebApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;

namespace GlobalExceptionHandler.Tests.WebApi.StatusCodeTests
{
public class StatusCodeAtRunTimeWithInt : IClassFixture<WebApiServerFixture>
{
private const string ApiProductNotFound = "/api/productnotfound";
private readonly HttpClient _client;

public StatusCodeAtRunTimeWithInt(WebApiServerFixture fixture)
{
// Arrange
var webHost = fixture.CreateWebHostWithMvc();
webHost.Configure(app =>
{
app.UseGlobalExceptionHandler(x =>
{
x.ContentType = "application/json";
x.Map<HttpNotFoundException>().ToStatusCode(ex => ex.StatusCodeInt);
x.ResponseBody(c => JsonConvert.SerializeObject(new TestResponse
{
Message = c.Message
}));
});
app.Map(ApiProductNotFound, config => { config.Run(context => throw new HttpNotFoundException("Record not found")); });
});

_client = new TestServer(webHost).CreateClient();
}

[Fact]
public async Task Returns_correct_response_type()
{
var response = await _client.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), ApiProductNotFound));
response.Content.Headers.ContentType.MediaType.ShouldBe("application/json");
}

[Fact]
public async Task Returns_correct_status_code()
{
var response = await _client.SendAsync(new HttpRequestMessage(new HttpMethod("GET"), ApiProductNotFound));
response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,39 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using GlobalExceptionHandler.Tests.Exceptions;
using GlobalExceptionHandler.Tests.Fixtures;
using GlobalExceptionHandler.WebApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;

namespace GlobalExceptionHandler.Tests.WebApi.StatusCodeTests
{
public class BasicTestsWithRunTimeStatusCode : IClassFixture<WebApiServerFixture>
public class BasicTestsEnum : IClassFixture<WebApiServerFixture>
{
private const string ApiProductNotFound = "/api/productnotfound";
private readonly HttpClient _client;

public BasicTestsWithRunTimeStatusCode(WebApiServerFixture fixture)
public BasicTestsEnum(WebApiServerFixture fixture)
{
// Arrange
const string requestUri = "/api/productnotfound";
var webHost = fixture.CreateWebHostWithMvc();
webHost.Configure(app =>
{
app.UseGlobalExceptionHandler(x =>
{
x.ContentType = "application/json";
x.Map<ArgumentException>().ToStatusCode(ex => ex is ArgumentException ? StatusCodes.Status400BadRequest : StatusCodes.Status500InternalServerError);
x.Map<ArgumentException>().ToStatusCode(HttpStatusCode.BadRequest);
x.ResponseBody(c => JsonConvert.SerializeObject(new TestResponse
{
Message = c.Message
}));
});
app.Map(requestUri, config => { config.Run(context => throw new ArgumentException("Invalid request")); });
app.Map(ApiProductNotFound, config => { config.Run(context => throw new ArgumentException("Invalid request")); });
});

_client = new TestServer(webHost).CreateClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using GlobalExceptionHandler.Tests.Exceptions;
using GlobalExceptionHandler.Tests.Fixtures;
using GlobalExceptionHandler.WebApi;
using Microsoft.AspNetCore.Builder;
Expand All @@ -15,12 +14,12 @@

namespace GlobalExceptionHandler.Tests.WebApi.StatusCodeTests
{
public class BasicTests : IClassFixture<WebApiServerFixture>
public class StatusCodeWithInt : IClassFixture<WebApiServerFixture>
{
private const string ApiProductNotFound = "/api/productnotfound";
private readonly HttpClient _client;

public BasicTests(WebApiServerFixture fixture)
public StatusCodeWithInt(WebApiServerFixture fixture)
{
// Arrange
var webHost = fixture.CreateWebHostWithMvc();
Expand Down
4 changes: 2 additions & 2 deletions src/GlobalExceptionHandler/GlobalExceptionHandler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<PackageId>GlobalExceptionHandler</PackageId>
<PackageTags>global exception handler;asp.net core;.net core</PackageTags>
<title>Global Exception Handling Middleware</title>
<VersionPrefix>4.0.0-beta1</VersionPrefix>
<PackageReleaseNotes>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet/releases/tag/4.0.0-beta</PackageReleaseNotes>
<VersionPrefix>4.0.0-beta2</VersionPrefix>
<PackageReleaseNotes>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet/releases/tag/4.0.0-beta2</PackageReleaseNotes>
<Authors>Joseph Woodward</Authors>
<Description>Global Exception Handler is middleware allowing you to handle exceptions by convention</Description>
<PackageProjectUrl>https://github.com/JosephWoodward/GlobalExceptionHandlerDotNet</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ public class ExceptionHandlerConfiguration : IUnhandledFormatters
var type = typeof(T);
return new ExceptionRuleCreator(_exceptionConfiguration, type);
}

public IHasStatusCode<TException> Map<TException>() where TException : Exception
{
return new ExceptionRuleCreator<TException>(_exceptionConfiguration);
}
=> new ExceptionRuleCreator<TException>(_exceptionConfiguration);

[Obsolete("MessageFormatter(..) is obsolete and will be removed soon, use ResponseBody(..) instead", false)]
public void MessageFormatter(Func<Exception, string> formatter)
Expand Down
14 changes: 13 additions & 1 deletion src/GlobalExceptionHandler/WebApi/ExceptionRuleCreator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

Expand All @@ -14,7 +15,9 @@ public interface IHasStatusCode
public interface IHasStatusCode<out TException> where TException: Exception
{
IHandledFormatters<TException> ToStatusCode(int statusCode);
IHandledFormatters<TException> ToStatusCode(HttpStatusCode statusCode);
IHandledFormatters<TException> ToStatusCode(Func<TException, int> statusCodeResolver);
IHandledFormatters<TException> ToStatusCode(Func<TException, HttpStatusCode> statusCodeResolver);
}

internal class ExceptionRuleCreator : IHasStatusCode, IHandledFormatters
Expand Down Expand Up @@ -104,9 +107,18 @@ public ExceptionRuleCreator(IDictionary<Type, ExceptionConfig> configurations)
}

public IHandledFormatters<TException> ToStatusCode(int statusCode)
=> ToStatusCode(ex => statusCode);
=> ToStatusCodeImpl(ex => statusCode);

public IHandledFormatters<TException> ToStatusCode(HttpStatusCode statusCode)
=> ToStatusCodeImpl(ex => (int)statusCode);

public IHandledFormatters<TException> ToStatusCode(Func<TException, int> statusCodeResolver)
=> ToStatusCodeImpl(statusCodeResolver);

public IHandledFormatters<TException> ToStatusCode(Func<TException, HttpStatusCode> statusCodeResolver)
=> ToStatusCodeImpl(x => (int)statusCodeResolver(x));

private IHandledFormatters<TException> ToStatusCodeImpl(Func<TException, int> statusCodeResolver)
{
int wrappedResolver(Exception x) => statusCodeResolver((TException)x);
var exceptionConfig = new ExceptionConfig
Expand Down

0 comments on commit 656f187

Please sign in to comment.