< Summary

Information
Class: ArturRios.Util.WebApi.AspNetCore.ResponseResolver
Assembly: ArturRios.Util.WebApi
File(s): D:\Repositories\dotnet-webapi-util\src\AspNetCore\ResponseResolver.cs
Line coverage
100%
Covered lines: 26
Uncovered lines: 0
Coverable lines: 26
Total lines: 77
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage
100%
Covered methods: 5
Fully covered methods: 1
Total methods: 5
Method coverage: 100%
Full method coverage: 20%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Resolve(...)100%11100%
Resolve(...)100%11100%
Resolve(...)100%11100%
ResolveStatusCode(...)100%1010100%
GetDefaultStatusCode(...)100%22100%

File(s)

D:\Repositories\dotnet-webapi-util\src\AspNetCore\ResponseResolver.cs

#LineLine coverage
 1using ArturRios.Output;
 2using ArturRios.Util.Http;
 3using Microsoft.AspNetCore.Mvc;
 4
 5namespace ArturRios.Util.WebApi.AspNetCore;
 6
 7/// <summary>Converts output envelopes from <c>ArturRios.Output</c> into ASP.NET Core <see cref="ActionResult{TValue}"/>
 8/// instances. The HTTP status is resolved in order: an explicit <c>statusCode</c>, then a lookup of the envelope's
 9/// first error (on failure) or first message (on success) in an optional <c>statusMap</c>, then a default of 200 on
 10/// success and 400 on failure.</summary>
 11public static class ResponseResolver
 12{
 13    /// <summary>Wraps a <see cref="PaginatedOutput{T}"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status is
 14    /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</summa
 15    /// <param name="paginatedOutput">The paginated result envelope to return.</param>
 16    /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.</pa
 17    /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an HTTP
 18    /// status code. The caller owns the dictionary and its key comparer.</param>
 19    public static ActionResult<PaginatedOutput<T>> Resolve<T>(PaginatedOutput<T> paginatedOutput,
 20        int? statusCode = null, IReadOnlyDictionary<string, int>? statusMap = null)
 121    {
 122        var httpStatusCode = ResolveStatusCode(paginatedOutput, statusCode, statusMap);
 23
 124        return new ObjectResult(paginatedOutput) { StatusCode = httpStatusCode };
 125    }
 26
 27    /// <summary>Wraps a <see cref="DataOutput{T}"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status is
 28    /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</summa
 29    /// <param name="dataOutput">The result envelope to return.</param>
 30    /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.</pa
 31    /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an HTTP
 32    /// status code. The caller owns the dictionary and its key comparer.</param>
 33    public static ActionResult<DataOutput<T?>> Resolve<T>(DataOutput<T?> dataOutput, int? statusCode = null,
 34        IReadOnlyDictionary<string, int>? statusMap = null)
 135    {
 136        var httpStatusCode = ResolveStatusCode(dataOutput, statusCode, statusMap);
 37
 138        return new ObjectResult(dataOutput) { StatusCode = httpStatusCode };
 139    }
 40
 41    /// <summary>Wraps a <see cref="ProcessOutput"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status is
 42    /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</summa
 43    /// <param name="processOutput">The result envelope to return.</param>
 44    /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.</pa
 45    /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an HTTP
 46    /// status code. The caller owns the dictionary and its key comparer.</param>
 47    public static ActionResult<ProcessOutput> Resolve(ProcessOutput processOutput, int? statusCode = null,
 48        IReadOnlyDictionary<string, int>? statusMap = null)
 849    {
 850        var httpStatusCode = ResolveStatusCode(processOutput, statusCode, statusMap);
 51
 852        return new ObjectResult(processOutput) { StatusCode = httpStatusCode };
 853    }
 54
 55    private static int ResolveStatusCode(ProcessOutput output, int? statusCode,
 56        IReadOnlyDictionary<string, int>? statusMap)
 1057    {
 1058        if (statusCode.HasValue)
 159        {
 160            return statusCode.Value;
 61        }
 62
 963        if (statusMap is not null)
 764        {
 765            var key = output.Success ? output.Messages.FirstOrDefault() : output.Errors.FirstOrDefault();
 66
 767            if (key is not null && statusMap.TryGetValue(key, out var mapped))
 568            {
 569                return mapped;
 70            }
 271        }
 72
 473        return GetDefaultStatusCode(output.Success);
 1074    }
 75
 476    private static int GetDefaultStatusCode(bool success) => success ? HttpStatusCodes.Ok : HttpStatusCodes.BadRequest;
 77}