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

AndreuCodina / CrossValidation / 5304511320

18 Jun 2023 03:52PM UTC coverage: 83.752% (-11.7%) from 95.463%
5304511320

Pull #40

github

web-flow
Merge ef6355e4d into d173638cd
Pull Request #40: Update coverage badge in README with pull requests

331 of 394 branches covered (84.01%)

Branch coverage included in aggregate %.

1035 of 1237 relevant lines covered (83.67%)

130.23 hits per line

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

0.0
/src/CrossValidation/DependencyInjection/CrossValidationMiddleware.cs
1
using System.Net;
2
using System.Text.Json;
3
using CrossValidation.Errors;
4
using CrossValidation.Exceptions;
5
using CrossValidation.Utils;
6
using Microsoft.AspNetCore.Hosting;
7
using Microsoft.AspNetCore.Http;
8
using Microsoft.Extensions.Logging;
9

10
namespace CrossValidation.DependencyInjection;
11

12
public class CrossValidationMiddleware : IMiddleware
13
{
14
    private bool _isExceptionHandled = false;
15
    private readonly ILogger<CrossValidationMiddleware> _logger;
16
    private readonly IHostingEnvironment _environment;
17

18
    public CrossValidationMiddleware(ILoggerFactory loggerFactory, IHostingEnvironment environment)
×
19
    {
20
        _logger = loggerFactory.CreateLogger<CrossValidationMiddleware>();
×
21
        _environment = environment;
×
22
    }
×
23
    
24
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
25
    {
26
        try
27
        {
28
            await next(context);
×
29
        }
×
30
        catch (Exception e)
×
31
        {
32
            await HandleException(e, context);
×
33

34
            if (!_isExceptionHandled)
×
35
            {
36
                throw;
×
37
            }
38
        }
39
    }
×
40

41
    private async Task HandleException(Exception exception, HttpContext context)
42
    {
43
        var problemDetails = new CrossProblemDetails();
×
44
        var httpStatusCode = HttpStatusCode.InternalServerError;
×
45
        string? title = null;
×
46
        string? details = null;
×
47
        List<CrossProblemDetailsError> errors = new();
×
48

49
        if (exception is CrossException crossException)
×
50
        {
51
            _isExceptionHandled = true;
×
52
            httpStatusCode = crossException.Error.HttpStatusCode ?? HttpStatusCode.UnprocessableEntity;
×
53
            title = "A validation error occurred";
×
54
            var error = CreateCrossProblemDetailsError(crossException.Error);
×
55
            
56
            var allErrorCustomizationsAreNotSet =
×
57
                error.Code is null
×
58
                && error.Message is null
×
59
                && error.Details is null
×
60
                && error.Placeholders is null;
×
61

62
            if (!allErrorCustomizationsAreNotSet)
×
63
            {
64
                errors.Add(error);
×
65
            }
66
        }
67
        else if (exception is ValidationListException validationListException)
×
68
        {
69
            _isExceptionHandled = true;
×
70
            httpStatusCode = HttpStatusCode.UnprocessableEntity;
×
71
            title = "Several validation errors occurred";
×
72

73
            foreach (var error in validationListException.Errors)
×
74
            {
75
                errors.Add(CreateCrossProblemDetailsError(error));
×
76
            }
77
        }
78
        else if (exception is NonNullablePropertyIsNullException nonNullablePropertyIsNullException)
×
79
        {
80
            _isExceptionHandled = true;
×
81
            httpStatusCode = HttpStatusCode.BadRequest;
×
82
            title = "Nullability error";
×
83
            details = $"Non nullable property is null: {nonNullablePropertyIsNullException.PropertyName}";
×
84
        }
85
        else if (exception is NonNullableItemCollectionWithNullItemException
×
86
                 nonNullableItemCollectionWithNullItemException)
×
87
        {
88
            _isExceptionHandled = true;
×
89
            httpStatusCode = HttpStatusCode.BadRequest;
×
90
            title = "Nullability error";
×
91
            details = $"Non nullable item collection with null item: {nonNullableItemCollectionWithNullItemException.CollectionName}";
×
92
        }
93
        else
94
        {
95
            if (!CrossValidationOptions.HandleUnknownException)
×
96
            {
97
                return;
×
98
            }
99
            
100
            _isExceptionHandled = true;
×
101
            _logger.LogError(exception, exception.Message);
×
102
            title = "An error occurred";;
×
103
            problemDetails.Detail = _environment.IsDevelopment() ? exception.Message : null;
×
104
        }
105

106
        problemDetails.Status = (int)httpStatusCode;
×
107
        problemDetails.Title = title;
×
108
        problemDetails.Detail = details;
×
109
        problemDetails.Errors = errors.Any() ? errors : null;
×
110
        var response = JsonSerializer.Serialize(problemDetails);
×
111
        context.Response.StatusCode = problemDetails.Status.Value;
×
112
        context.Response.ContentType = "application/problem+json";
×
113
        context.Response.Headers.Add("X-Trace-Id", context.Request.Headers["X-Trace-Id"]);
×
114
        await context.Response.WriteAsync(response);
×
115
    }
×
116

117
    private CrossProblemDetailsError CreateCrossProblemDetailsError(ICrossError crossError)
118
    {
119
        var error = new CrossProblemDetailsError
×
120
        {
×
121
            Code = crossError.Code,
×
122
            Message = crossError.Message,
×
123
            Details = crossError.Details
×
124
        };
×
125

126
        if (CrossValidationOptions.LocalizeErrorInClient
×
127
            && crossError.PlaceholderValues is not null)
×
128
        {
129
            var placeholders = new Dictionary<string, object>();
×
130
            
131
            foreach (var placeholder in crossError.PlaceholderValues)
×
132
            {
133
                placeholders.Add(placeholder.Key, placeholder.Value);
×
134
            }
135

136
            error.Placeholders = placeholders;
×
137
        }
138

139
        return error;
×
140
    }
141
}
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