< Summary

Information
Class: ProjectTemplate.Web.Controllers.HomeController
Assembly: ProjectTemplate.Web
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Controllers/HomeController.cs
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 128
Line coverage: 100%
Branch coverage
79%
Covered branches: 19
Total branches: 24
Branch coverage: 79.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Error(...)87.5%1616100%
ResolveStatusCode(...)62.5%88100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Controllers/HomeController.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Diagnostics;
 3using Microsoft.AspNetCore.Mvc;
 4using ProjectTemplate.Web.Constants;
 5using ProjectTemplate.Web.Diagnostics;
 6using ProjectTemplate.Web.Models;
 7
 8namespace ProjectTemplate.Web.Controllers;
 9
 10/// <summary>
 11/// Controller for handling the home page and error routes.
 12/// </summary>
 13/// <param name="logger">The logger instance for the controller.</param>
 2914public partial class HomeController(ILogger<HomeController> logger) : Controller
 15{
 2916    private readonly ILogger<HomeController> _logger = logger;
 17
 18    /// <summary>
 19    /// Displays an error page for a request routed here by the error-handling pipeline. The response status
 20    /// code comes from the pipeline rather than the route value, and a request that did not arrive through
 21    /// the pipeline is answered with 404 instead of the error page.
 22    /// </summary>
 23    /// <remarks>
 24    /// This route is anonymous by necessity, since it serves errors for unauthenticated requests. Trusting its
 25    /// route value would let any caller choose the response status code — including values outside the valid
 26    /// range, such as <c>/Home/Error/0</c> or <c>/Home/Error/999</c> — and emit a warning-level log entry per
 27    /// request. The presence of <see cref="IStatusCodeReExecuteFeature" /> or
 28    /// <see cref="IExceptionHandlerPathFeature" /> is what distinguishes a re-executed request from a direct one.
 29    /// </remarks>
 30    /// <param name="statusCode">Status code supplied by the status-code re-execute route. Ignored for direct requests.<
 31    /// <returns>The error view for a pipeline-routed request; otherwise a 404 result.</returns>
 32    [AllowAnonymous]
 33    [Route("Home/Error/{statusCode:int?}")]
 34    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
 35    public IActionResult Error(int? statusCode = null)
 36    {
 2937        IExceptionHandlerPathFeature? exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
 2938        IStatusCodeReExecuteFeature? statusCodeFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
 39
 40        // A request that reaches this route directly carries neither feature. It is answered as not found, so
 41        // the route value cannot select the response status and cannot generate error-page log entries.
 2942        if (exceptionFeature is null && statusCodeFeature is null)
 43        {
 644            return NotFound();
 45        }
 46
 2347        int resolvedStatusCode = ResolveStatusCode(statusCodeFeature, statusCode);
 48
 2349        Response.StatusCode = resolvedStatusCode;
 50
 2351        string originalPath =
 2352            exceptionFeature?.Path ??
 2353            statusCodeFeature?.OriginalPath ??
 2354            HttpContext.Request.Path.ToString();
 55
 2356        string? remoteIpAddress = RequestLoggingPrivacy.GetLoggableRemoteIpAddress(HttpContext);
 57
 2358        string requestId = HttpContext.TraceIdentifier;
 59
 2360        if (exceptionFeature?.Error is not null)
 61        {
 162            LogUnhandledExceptionRoutedToErrorPage(
 163                _logger,
 164                exceptionFeature.Error,
 165                resolvedStatusCode,
 166                originalPath,
 167                remoteIpAddress,
 168                requestId);
 69        }
 70        else
 71        {
 2272            LogStatusCodePageRoutedToErrorPage(
 2273                _logger,
 2274                resolvedStatusCode,
 2275                originalPath,
 2276                remoteIpAddress,
 2277                requestId);
 78        }
 79
 2380        return View(new ErrorViewModel
 2381        {
 2382            StatusCode = resolvedStatusCode,
 2383            RequestId = requestId
 2384        });
 85    }
 86
 87    /// <summary>
 88    /// Resolves the status code to return, preferring the value the pipeline recorded over the route value.
 89    /// </summary>
 90    /// <param name="statusCodeFeature">The status-code re-execute feature, when the request was re-executed.</param>
 91    /// <param name="routeStatusCode">The status code bound from the route.</param>
 92    /// <returns>A status code inside the range the error page serves.</returns>
 93    private static int ResolveStatusCode(IStatusCodeReExecuteFeature? statusCodeFeature, int? routeStatusCode)
 94    {
 2395        int resolvedStatusCode = statusCodeFeature?.OriginalStatusCode
 2396            ?? routeStatusCode
 2397            ?? StatusCodes.Status500InternalServerError;
 98
 99        // Status-code pages re-execute for client and server errors only. Anything outside that range means the
 100        // value did not come from the pipeline, so it is not written to the response.
 23101        return resolvedStatusCode is < StatusCodes.Status400BadRequest or > 599
 23102            ? StatusCodes.Status500InternalServerError
 23103            : resolvedStatusCode;
 104    }
 105
 106    [LoggerMessage(
 107        EventId = ApplicationLogEventIds.UnhandledExceptionRoutedToErrorPage,
 108        Level = LogLevel.Error,
 109        Message = "Unhandled exception routed to error page. StatusCode: {StatusCode}; OriginalPath: {OriginalPath}; Rem
 110    private static partial void LogUnhandledExceptionRoutedToErrorPage(
 111        ILogger logger,
 112        Exception exception,
 113        int statusCode,
 114        string originalPath,
 115        string? remoteIpAddress,
 116        string traceIdentifier);
 117
 118    [LoggerMessage(
 119        EventId = ApplicationLogEventIds.StatusCodePageRoutedToErrorPage,
 120        Level = LogLevel.Warning,
 121        Message = "Status code page routed to error page. StatusCode: {StatusCode}; OriginalPath: {OriginalPath}; Remote
 122    private static partial void LogStatusCodePageRoutedToErrorPage(
 123        ILogger logger,
 124        int statusCode,
 125        string originalPath,
 126        string? remoteIpAddress,
 127        string traceIdentifier);
 128}