Skip to content

Commit 95ac4a0

Browse files
committed
Improve and unify WithErrors() method for API errors.
1 parent a7d1929 commit 95ac4a0

File tree

4 files changed

+39
-21
lines changed

4 files changed

+39
-21
lines changed

src/Initium/Attributes/ValidateModelAttribute.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ public void OnActionExecuting(ActionExecutingContext context)
3333
.CreateFromContext(context.HttpContext)
3434
.WithMessage("One or more validation errors occurred.")
3535
.WithStatusCode(HttpStatusCode.BadRequest)
36-
.WithErrors(validationResult.Errors)
36+
.WithErrors(validationResult.Errors
37+
.Select(validationFailure => new ApiError(validationFailure.ErrorCode, validationFailure.ErrorMessage))
38+
.ToArray())
3739
.BuildAsJsonResult();
3840
}
3941

src/Initium/Filters/ImplicitValidationFilter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ public void OnActionExecuting(ActionExecutingContext context)
3737
.CreateFromContext(context.HttpContext)
3838
.WithMessage("One or more validation errors occurred.")
3939
.WithStatusCode(HttpStatusCode.BadRequest)
40-
.WithErrors(validationResult.Errors)
40+
.WithErrors(validationResult.Errors
41+
.Select(validationFailure => new ApiError(validationFailure.ErrorCode, validationFailure.ErrorMessage))
42+
.ToArray())
4143
.BuildAsJsonResult();
4244
}
4345

src/Initium/Response/ApiResponseBuilder.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System.Diagnostics.CodeAnalysis;
22
using System.Net;
3-
using FluentValidation.Results;
43
using Microsoft.AspNetCore.Http;
54
using Microsoft.AspNetCore.Mvc;
6-
using Microsoft.AspNetCore.Mvc.ModelBinding;
75

86
namespace Initium.Response;
97

@@ -79,18 +77,37 @@ public ApiResponseBuilder WithErrors(params ApiError[] errors)
7977
}
8078

8179
/// <summary>
82-
/// Adds a list of validation errors to the API response.
80+
/// Adds a custom header to the API response.
8381
/// </summary>
84-
/// <param name="validationResultErrors">The list of validation failures to include in the response.</param>
85-
/// <returns>The current instance of the <see cref="ApiResponseBuilder"/>.</returns>
86-
public ApiResponseBuilder WithErrors(List<ValidationFailure> validationResultErrors)
82+
/// <param name="headerName">The name of the header to be added.</param>
83+
/// <param name="headerValue">The value for the specified header.</param>
84+
/// <returns>The current instance of <see cref="ApiResponseBuilder"/> with the custom header added.</returns>
85+
/// <exception cref="ArgumentException">Thrown when <paramref name="headerName"/> is null, empty, or consists only of white-space characters.</exception>
86+
public ApiResponseBuilder WithCustomHeader(string headerName, string headerValue)
8787
{
88-
_apiResponse.Errors = validationResultErrors
89-
.Select(validationFailure => new ApiError(validationFailure.ErrorCode, validationFailure.ErrorMessage))
90-
.ToList();
88+
if (string.IsNullOrWhiteSpace(headerName))
89+
throw new ArgumentException("Header name cannot be null or empty.", nameof(headerName));
90+
91+
_apiResponse.CustomHeaders ??= new Dictionary<string, string>();
92+
_apiResponse.CustomHeaders[headerName] = headerValue;
9193
return this;
9294
}
9395

96+
/// <summary>
97+
/// Adds custom headers to the API response.
98+
/// </summary>
99+
/// <param name="headers">A dictionary containing header names as keys and their respective values.</param>
100+
/// <returns>The current instance of <see cref="ApiResponseBuilder"/> with the added custom headers.</returns>
101+
/// <exception cref="ArgumentException">Thrown when the <paramref name="headers"/> dictionary is null or empty.</exception>
102+
public ApiResponseBuilder WithCustomHeaders(Dictionary<string, string> headers)
103+
{
104+
_apiResponse.CustomHeaders ??= new Dictionary<string, string>();
105+
foreach (var header in headers)
106+
_apiResponse.CustomHeaders[header.Key] = header.Value;
107+
108+
return this;
109+
}
110+
94111
/// <summary>
95112
/// Builds and returns the constructed <see cref="ApiResponse"/>.
96113
/// </summary>
@@ -105,14 +122,4 @@ public ApiResponseBuilder WithErrors(List<ValidationFailure> validationResultErr
105122
{
106123
StatusCode = _apiResponse.StatusCode
107124
};
108-
109-
public ApiResponseBuilder WithCustomHeader(string headerName, string headerValue)
110-
{
111-
if (string.IsNullOrWhiteSpace(headerName))
112-
throw new ArgumentException("Header name cannot be null or empty.", nameof(headerName));
113-
114-
_apiResponse.CustomHeaders ??= new Dictionary<string, string>();
115-
_apiResponse.CustomHeaders[headerName] = headerValue;
116-
return this;
117-
}
118125
}

src/Initium/Results/InvalidModelStateResult.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,18 @@ public class InvalidModelStateResult : JsonResult
1616
/// <param name="actionContext">The context of the action where the model validation failed.</param>
1717
public InvalidModelStateResult(ActionContext actionContext) : base(actionContext)
1818
{
19+
var validationErrors = actionContext.ModelState
20+
.Where(ms => ms.Value != null && ms.Value.Errors.Any())
21+
.SelectMany(ms => ms.Value?.Errors.Select(error =>
22+
new ApiError(ms.Key, error.ErrorMessage)) ?? Array.Empty<ApiError>())
23+
.ToArray();
24+
1925
// Create a standardized API response using the HTTP context.
2026
StatusCode = StatusCodes.Status400BadRequest;
2127
Value = ApiResponseBuilder.CreateFromContext(actionContext.HttpContext)
2228
.WithMessage("One or more validation errors occurred.")
2329
.WithStatusCode(HttpStatusCode.BadRequest)
30+
.WithErrors(validationErrors)
2431
.Build();
2532
}
2633
}

0 commit comments

Comments
 (0)