• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mehdihadeli / tdd-sample / 5637763153

pending completion
5637763153

push

github

mehdihadeli
fix: :bug: bug fix in handling exception in problemdetail

32 of 114 branches covered (28.07%)

Branch coverage included in aggregate %.

27 of 27 new or added lines in 1 file covered. (100.0%)

526 of 803 relevant lines covered (65.5%)

11.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.89
/src/TDDSample/Shared/ProblemDetail/ProblemDetailsService.cs
1
using Microsoft.AspNetCore.Diagnostics;
2
using Microsoft.AspNetCore.Http;
3
using Microsoft.AspNetCore.Mvc;
4

5
namespace TDDSample.Shared.ProblemDetail;
6

7

8
// https://www.strathweb.com/2022/08/problem-details-responses-everywhere-with-asp-net-core-and-net-7/
9
public class ProblemDetailsService : IProblemDetailsService
10
{
11
    private readonly IEnumerable<IProblemDetailMapper>? _problemDetailMappers;
12
    private readonly IProblemDetailsWriter[] _writers;
13

14
    public ProblemDetailsService(
3✔
15
        IEnumerable<IProblemDetailsWriter> writers,
3✔
16
        IEnumerable<IProblemDetailMapper>? problemDetailMappers = null
3✔
17
    )
3✔
18
    {
3✔
19
        _writers = writers.ToArray();
3✔
20
        _problemDetailMappers = problemDetailMappers;
3✔
21
    }
3✔
22

23
    public ValueTask WriteAsync(ProblemDetailsContext context)
24
    {
×
25
        ArgumentNullException.ThrowIfNull((object)context, nameof(context));
×
26
        ArgumentNullException.ThrowIfNull((object)context.ProblemDetails, "context.ProblemDetails");
×
27
        ArgumentNullException.ThrowIfNull((object)context.HttpContext, "context.HttpContext");
×
28

29
        // with help of `capture exception middleware` for capturing actual thrown exception, in .net 8 preview 5 it will create automatically
30
        IExceptionHandlerFeature? exceptionFeature =
×
31
            context.HttpContext.Features.Get<IExceptionHandlerFeature>();
×
32

33
        // if we throw an exception, we should create appropriate ProblemDetail based on the exception, else we just return default ProblemDetail with status 500 or a custom ProblemDetail which is returned from the endpoint
34
        if (exceptionFeature is not null)
×
35
        {
×
36
            CreateProblemDetailFromException(context, exceptionFeature);
×
37
        }
×
38

39
        if (
×
40
            context.HttpContext.Response.HasStarted
×
41
            || context.HttpContext.Response.StatusCode < 400
×
42
            || _writers.Length == 0
×
43
        )
×
44
            return ValueTask.CompletedTask;
×
45

46
        IProblemDetailsWriter problemDetailsWriter = null!;
×
47
        if (_writers.Length == 1)
×
48
        {
×
49
            IProblemDetailsWriter writer = _writers[0];
×
50
            return !writer.CanWrite(context) ? ValueTask.CompletedTask : writer.WriteAsync(context);
×
51
        }
52

53
        foreach (var writer in _writers)
×
54
        {
×
55
            if (writer.CanWrite(context))
×
56
            {
×
57
                problemDetailsWriter = writer;
×
58
                break;
×
59
            }
60
        }
×
61

62
        return problemDetailsWriter?.WriteAsync(context) ?? ValueTask.CompletedTask;
×
63
    }
×
64

65
    private void CreateProblemDetailFromException(
66
        ProblemDetailsContext context,
67
        IExceptionHandlerFeature exceptionFeature
68
    )
69
    {
×
70
        if (_problemDetailMappers is { })
×
71
        {
×
72
            foreach (var problemDetailMapper in _problemDetailMappers)
×
73
            {
×
74
                var mappedStatusCode = problemDetailMapper.GetMappedStatusCodes(
×
75
                    exceptionFeature.Error
×
76
                );
×
77
                if (mappedStatusCode > 0)
×
78
                {
×
79
                    PopulateNewProblemDetail(
×
80
                        context.ProblemDetails,
×
81
                        context.HttpContext,
×
82
                        mappedStatusCode,
×
83
                        exceptionFeature.Error
×
84
                    );
×
85
                    context.HttpContext.Response.StatusCode = mappedStatusCode;
×
86
                }
×
87
            }
×
88
        }
×
89
    }
×
90

91
    private static void PopulateNewProblemDetail(
92
        ProblemDetails existingProblemDetails,
93
        HttpContext httpContext,
94
        int statusCode,
95
        Exception exception
96
    )
97
    {
×
98
        existingProblemDetails.Title = exception.GetType().Name;
×
99
        existingProblemDetails.Detail = exception.Message;
×
100
        existingProblemDetails.Status = statusCode;
×
101
        existingProblemDetails.Instance =
×
102
            $"{httpContext.Request.Method} {httpContext.Request.Path}";
×
103
    }
×
104
}
105

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc