Skip to content

Commit 9676990

Browse files
author
Bart Koelman
committed
Fixed: use status code from error; unwrap reflection errors
1 parent 7c40384 commit 9676990

File tree

6 files changed

+102
-1
lines changed

6 files changed

+102
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using JsonApiDotNetCore.Configuration;
2+
using JsonApiDotNetCore.Controllers;
3+
using JsonApiDotNetCore.Services;
4+
using JsonApiDotNetCoreExample.Models;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace JsonApiDotNetCoreExample.Controllers
8+
{
9+
public sealed class ThrowingResourcesController : JsonApiController<ThrowingResource>
10+
{
11+
public ThrowingResourcesController(
12+
IJsonApiOptions jsonApiOptions,
13+
ILoggerFactory loggerFactory,
14+
IResourceService<ThrowingResource> resourceService)
15+
: base(jsonApiOptions, loggerFactory, resourceService)
16+
{ }
17+
}
18+
}

src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public sealed class AppDbContext : DbContext
1919
public DbSet<ArticleTag> ArticleTags { get; set; }
2020
public DbSet<IdentifiableArticleTag> IdentifiableArticleTags { get; set; }
2121
public DbSet<Tag> Tags { get; set; }
22+
public DbSet<ThrowingResource> ThrowingResources { get; set; }
2223

2324
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
2425

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Linq;
4+
using JsonApiDotNetCore.Formatters;
5+
using JsonApiDotNetCore.Models;
6+
7+
namespace JsonApiDotNetCoreExample.Models
8+
{
9+
public sealed class ThrowingResource : Identifiable
10+
{
11+
[Attr]
12+
public string FailsOnSerialize
13+
{
14+
get
15+
{
16+
var isSerializingResponse = new StackTrace().GetFrames()
17+
.Any(frame => frame.GetMethod().DeclaringType == typeof(JsonApiWriter));
18+
19+
if (isSerializingResponse)
20+
{
21+
throw new InvalidOperationException($"The value for the '{nameof(FailsOnSerialize)}' property is currently unavailable.");
22+
}
23+
24+
return string.Empty;
25+
}
26+
set { }
27+
}
28+
}
29+
}

src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Net;
44
using System.Net.Http;
5+
using System.Reflection;
56
using System.Text;
67
using System.Threading.Tasks;
78
using JsonApiDotNetCore.Exceptions;
@@ -54,6 +55,8 @@ public async Task WriteAsync(OutputFormatterWriteContext context)
5455
{
5556
var errorDocument = _exceptionHandler.HandleException(exception);
5657
responseContent = _serializer.Serialize(errorDocument);
58+
59+
response.StatusCode = (int)errorDocument.GetErrorStatusCode();
5760
}
5861
}
5962

@@ -79,6 +82,10 @@ private string SerializeResponse(object contextObject, HttpStatusCode statusCode
7982
{
8083
return _serializer.Serialize(contextObject);
8184
}
85+
catch (TargetInvocationException exception)
86+
{
87+
throw new InvalidResponseBodyException(exception.InnerException);
88+
}
8289
catch (Exception exception)
8390
{
8491
throw new InvalidResponseBodyException(exception);

src/JsonApiDotNetCore/Serialization/Server/ResponseSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ private string SerializeErrorDocument(ErrorDocument errorDocument)
8383
/// </remarks>
8484
internal string SerializeSingle(IIdentifiable entity)
8585
{
86-
if (RequestRelationship != null)
86+
if (RequestRelationship != null && entity != null)
8787
return JsonConvert.SerializeObject(((ResponseResourceObjectBuilder)_resourceObjectBuilder).Build(entity, RequestRelationship));
8888

8989
var (attributes, relationships) = GetFieldsToSerialize();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Linq;
2+
using System.Net;
3+
using System.Threading.Tasks;
4+
using JsonApiDotNetCore.Models.JsonApiDocuments;
5+
using JsonApiDotNetCoreExample.Models;
6+
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Linq;
8+
using Xunit;
9+
10+
namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec
11+
{
12+
public class ThrowingResourceTests : FunctionalTestCollection<StandardApplicationFactory>
13+
{
14+
public ThrowingResourceTests(StandardApplicationFactory factory) : base(factory)
15+
{
16+
}
17+
18+
[Fact]
19+
public async Task GetThrowingResource_Fails()
20+
{
21+
// Arrange
22+
var throwingResource = new ThrowingResource();
23+
_dbContext.Add(throwingResource);
24+
_dbContext.SaveChanges();
25+
26+
// Act
27+
var (body, response) = await Get($"/api/v1/throwingResources/{throwingResource.Id}");
28+
29+
// Assert
30+
AssertEqualStatusCode(HttpStatusCode.InternalServerError, response);
31+
32+
var errorDocument = JsonConvert.DeserializeObject<ErrorDocument>(body);
33+
34+
Assert.Single(errorDocument.Errors);
35+
Assert.Equal(HttpStatusCode.InternalServerError, errorDocument.Errors[0].StatusCode);
36+
Assert.Equal("Failed to serialize response body.", errorDocument.Errors[0].Title);
37+
Assert.Equal("The value for the 'FailsOnSerialize' property is currently unavailable.", errorDocument.Errors[0].Detail);
38+
39+
var stackTraceLines =
40+
((JArray) errorDocument.Errors[0].Meta.Data["stackTrace"]).Select(token => token.Value<string>());
41+
42+
Assert.Contains(stackTraceLines, line => line.Contains(
43+
"System.InvalidOperationException: The value for the 'FailsOnSerialize' property is currently unavailable."));
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)