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

AndreuCodina / CrossValidation / 6145209392

11 Sep 2023 10:33AM UTC coverage: 96.199% (+2.8%) from 93.42%
6145209392

Pull #88

github

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

471 of 516 branches covered (0.0%)

Branch coverage included in aggregate %.

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

1655 of 1694 relevant lines covered (97.7%)

167.17 hits per line

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

94.39
/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();
46✔
18
        _environment = serviceProvider.GetRequiredService<IHostEnvironment>();
46✔
19
        options?.Invoke(new CrossValidationOptionsBuilder());
46✔
20
        AddHttpResponseCustomizers(services);
46✔
21
        return services;
46✔
22
    }
23

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

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

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

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

90✔
64
                AddExceptionExtension(context);
44✔
65
                AddTraceIdExtension(context);
44✔
66
            });
134✔
67
    }
45✔
68

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

77
    private static void AddExceptionExtension(ProblemDetailsContext context)
78
    {
79
        if (context.Exception is null || !_environment.IsDevelopment())
44✔
80
        {
81
            return;
12✔
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;
34✔
102
        
103
        if (!CrossValidationOptions.IsErrorCodePageEnabled || exception.Code is null)
34✔
104
        {
105
            return;
31✔
106
        }
107
    
108
        if (CrossValidationOptions.PublicationUrl is not null)
3✔
109
        {
110
            baseUrl = CrossValidationOptions.PublicationUrl;
1✔
111
        }
112
        else if (_environment.IsDevelopment())
2✔
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;
1✔
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