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

AndreuCodina / CrossValidation / 6145012489

11 Sep 2023 10:15AM UTC coverage: 96.067% (+2.6%) from 93.42%
6145012489

Pull #88

github

web-flow
Merge 917fbe270 into d3ce57897
Pull Request #88: Update problem details

470 of 516 branches covered (0.0%)

Branch coverage included in aggregate %.

98 of 98 new or added lines in 10 files covered. (100.0%)

1655 of 1696 relevant lines covered (97.58%)

166.8 hits per line

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

92.52
/src/CrossValidation.AspNetCore/CrossValidationServiceCollectionExtensions.cs
1
using System.Diagnostics;
2
using CrossValidation.Exceptions;
3
using Microsoft.AspNetCore.Http;
4
using Microsoft.Extensions.DependencyInjection;
5
using Microsoft.Extensions.Hosting;
6

7
namespace CrossValidation.AspNetCore;
8

9
public static class CrossValidationServiceCollectionExtensions
10
{
11
    private static IHostEnvironment _environment = default!;
12
    
13
    public static IServiceCollection AddCrossValidation(
14
        this IServiceCollection services,
15
        Action<CrossValidationOptionsBuilder>? options = null)
16
    {
17
        var serviceProvider = services.BuildServiceProvider();
45✔
18
        _environment = serviceProvider.GetRequiredService<IHostEnvironment>();
45✔
19
        options?.Invoke(new CrossValidationOptionsBuilder());
45✔
20
        AddHttpResponseCustomizers(services);
45✔
21
        return services;
45✔
22
    }
23

24
    private static void AddHttpResponseCustomizers(IServiceCollection services)
25
    {
26
        if (!CrossValidationOptions.CustomizeHttpResponse)
45✔
27
        {
28
            return;
1✔
29
        }
30

31
        AddProblemDetails(services);
44✔
32
        AddBusinessExceptionMiddleware(services);
44✔
33
    }
44✔
34

35
    private static void AddBusinessExceptionMiddleware(IServiceCollection services)
36
    {
37
        services.AddTransient<BusinessExceptionMiddleware>();
44✔
38
    }
44✔
39

40
    private static void AddProblemDetails(IServiceCollection services)
41
    {
42
        services.AddProblemDetails(problemDetailsOptions =>
44✔
43
            problemDetailsOptions.CustomizeProblemDetails = context =>
88✔
44
            {
88✔
45
                if (context.Exception is BusinessException businessException)
43✔
46
                {
88✔
47
                    AddCodeUrl(businessException, context);
33✔
48
                    var mapper = new ProblemDetailsMapper(context.ProblemDetails);
33✔
49
                    mapper.Map(businessException);
33✔
50
                    context.HttpContext.Response.StatusCode = (int)context.ProblemDetails.Status!;
33✔
51
                }
88✔
52
                else if (context.Exception is BusinessListException businessListException)
10✔
53
                {
88✔
54
                    foreach (var exception in businessListException.Exceptions)
6!
55
                    {
88✔
56
                        AddCodeUrl(exception, context);
×
57
                    }
88✔
58
                    
88✔
59
                    var mapper = new ProblemDetailsMapper(context.ProblemDetails);
3✔
60
                    mapper.Map(businessListException);
3✔
61
                    context.HttpContext.Response.StatusCode = (int)context.ProblemDetails.Status!;
3✔
62
                }
88✔
63

88✔
64
                AddExceptionExtension(context);
43✔
65
                AddTraceIdExtension(context);
43✔
66
            });
131✔
67
    }
44✔
68

69
    private static void AddTraceIdExtension(ProblemDetailsContext context)
70
    {
71
        var traceId = Activity.Current?.Id ?? context.HttpContext.TraceIdentifier;
43!
72
        context.ProblemDetails
43✔
73
            .Extensions
43✔
74
            .Add(CrossValidationProblemDetails.TraceIdPropertyName, traceId);
43✔
75
    }
43✔
76

77
    private static void AddExceptionExtension(ProblemDetailsContext context)
78
    {
79
        if (context.Exception is null || !_environment.IsDevelopment())
43✔
80
        {
81
            return;
11✔
82
        }
83

84
        var exceptionExtension = new CrossValidationProblemDetailsException
32✔
85
        {
32✔
86
            Details = context.Exception.ToString(),
32✔
87
            Headers = context.HttpContext
32✔
88
                .Request
32✔
89
                .Headers
32✔
90
                .ToDictionary(x => x.Key, x => x.Value.ToList()),
96✔
91
            Path = context.HttpContext.Request.Path,
32✔
92
            Endpoint = context.HttpContext.GetEndpoint()?.ToString()
32✔
93
        };
32✔
94
        context.ProblemDetails
32✔
95
            .Extensions
32✔
96
            .Add(CrossValidationProblemDetails.ExceptionPropertyName, exceptionExtension);
32✔
97
    }
32✔
98
    
99
    private static void AddCodeUrl(BusinessException exception, ProblemDetailsContext context)
100
    {
101
        string? baseUrl = null;
33✔
102
        
103
        if (!CrossValidationOptions.IsErrorCodePageEnabled || exception.Code is null)
33✔
104
        {
105
            return;
31✔
106
        }
107
    
108
        if (CrossValidationOptions.PublicationUrl is not null)
2✔
109
        {
110
            baseUrl = CrossValidationOptions.PublicationUrl;
1✔
111
        }
112
        else if (_environment.IsDevelopment())
1!
113
        {
114
            var protocol = context.HttpContext.Request.IsHttps ? "https" : "http";
1!
115
            var host = context.HttpContext.Request.Host.Value;
1✔
116
            var port = context.HttpContext.Request.Host.Port is not null
1!
117
                ? $":{context.HttpContext.Request.Host.Port.Value}"
1✔
118
                : null;
1✔
119
            baseUrl = $"{protocol}://{host}{port}";
1✔
120
        }
121
        else
122
        {
123
            return;
×
124
        }
125
        
126
        var codeUrl = $"{baseUrl}/{CrossValidationOptions.ErrorCodePagePath}#{exception.Code}";
2✔
127
        exception.CodeUrl = codeUrl;
2✔
128
    }
2✔
129
}
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

© 2025 Coveralls, Inc