< Summary

Information
Class: ArturRios.Util.WebApi.AspNetCore.OutputActionResultExtensions
Assembly: ArturRios.Util.WebApi
File(s): /home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/AspNetCore/OutputActionResultExtensions.cs
Line coverage
100%
Covered lines: 10
Uncovered lines: 0
Coverable lines: 10
Total lines: 76
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage
100%
Covered methods: 4
Fully covered methods: 4
Total methods: 4
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ToActionResult(...)100%11100%
ToActionResult(...)100%11100%
ToActionResult(...)100%11100%
ResolveStatusCode(...)100%1212100%

File(s)

/home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/AspNetCore/OutputActionResultExtensions.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 OutputActionResultExtensions
 12{
 13    /// <param name="paginatedOutput">The paginated result envelope to return.</param>
 14    extension<T>(PaginatedOutput<T> paginatedOutput)
 15    {
 16        /// <summary>Wraps a <see cref="PaginatedOutput{T}"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status 
 17        /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</s
 18        /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.
 19        /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an H
 20        /// status code. The caller owns the dictionary and its key comparer.</param>
 21        public ActionResult<PaginatedOutput<T>> ToActionResult(int? statusCode = null,
 22            IReadOnlyDictionary<string, int>? statusMap = null) =>
 123            new ObjectResult(paginatedOutput) { StatusCode = paginatedOutput.ResolveStatusCode(statusCode, statusMap) };
 24    }
 25
 26    /// <param name="dataOutput">The result envelope to return.</param>
 27    extension<T>(DataOutput<T?> dataOutput)
 28    {
 29        /// <summary>Wraps a <see cref="DataOutput{T}"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status is
 30        /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</s
 31        /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.
 32        /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an H
 33        /// status code. The caller owns the dictionary and its key comparer.</param>
 34        public ActionResult<DataOutput<T?>> ToActionResult(int? statusCode = null,
 35            IReadOnlyDictionary<string, int>? statusMap = null) =>
 136            new ObjectResult(dataOutput) { StatusCode = dataOutput.ResolveStatusCode(statusCode, statusMap) };
 37    }
 38
 39    /// <param name="output">The result envelope.</param>
 40    extension(ProcessOutput output)
 41    {
 42        /// <summary>Wraps a <see cref="ProcessOutput"/> in an <see cref="ActionResult{TValue}"/>. The HTTP status is
 43        /// resolved from <paramref name="statusCode"/>, then <paramref name="statusMap"/>, then the 200/400 default.</s
 44        /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.
 45        /// <param name="statusMap">Optional map from the first error (on failure) or first message (on success) to an H
 46        /// status code. The caller owns the dictionary and its key comparer.</param>
 47        public ActionResult<ProcessOutput> ToActionResult(int? statusCode = null,
 48            IReadOnlyDictionary<string, int>? statusMap = null) =>
 849            new ObjectResult(output) { StatusCode = output.ResolveStatusCode(statusCode, statusMap) };
 50
 51        /// <summary>Resolves the HTTP status code for the envelope: <paramref name="statusCode"/> when supplied, then t
 52        /// <paramref name="statusMap"/> entry for the envelope's first error (on failure) or first message (on success)
 53        /// then 200 on success and 400 on failure.</summary>
 54        /// <param name="statusCode">Optional explicit HTTP status code; when supplied it wins over the map and default.
 55        /// <param name="statusMap">Optional map from the first error or message to an HTTP status code.</param>
 56        public int ResolveStatusCode(int? statusCode = null, IReadOnlyDictionary<string, int>? statusMap = null)
 57        {
 1058            if (statusCode.HasValue)
 59            {
 160                return statusCode.Value;
 61            }
 62
 963            if (statusMap is not null)
 64            {
 765                var key = output.Success ? output.Messages.FirstOrDefault() : output.Errors.FirstOrDefault();
 66
 767                if (key is not null && statusMap.TryGetValue(key, out var mapped))
 68                {
 569                    return mapped;
 70                }
 71            }
 72
 473            return output.Success ? HttpStatusCodes.Ok : HttpStatusCodes.BadRequest;
 74        }
 75    }
 76}