< Summary

Information
Class: ArturRios.Util.WebApi.Configuration.WebApiStartup
Assembly: ArturRios.Util.WebApi
File(s): /home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/Configuration/WebApiStartup.cs
Line coverage
90%
Covered lines: 28
Uncovered lines: 3
Coverable lines: 31
Total lines: 103
Line coverage: 90.3%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage
62%
Covered methods: 5
Fully covered methods: 5
Total methods: 8
Method coverage: 62.5%
Full method coverage: 62.5%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
.ctor(...)100%11100%
get_Parameters()100%11100%
get_Options()100%11100%
get_Builder()100%11100%
Build()100%44100%
Run()100%210%
RunAsync()100%210%

File(s)

/home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/Configuration/WebApiStartup.cs

#LineLine coverage
 1using ArturRios.Util.WebApi.Middleware;
 2using Microsoft.AspNetCore.Builder;
 3using Microsoft.Extensions.DependencyInjection;
 4
 5namespace ArturRios.Util.WebApi.Configuration;
 6
 7/// <summary>
 8/// Base class that bootstraps an ASP.NET Core web API through one standard sequence. A derived class only registers
 9/// its own services in <see cref="ConfigureServices"/>; the rest runs in this order:
 10/// <list type="number">
 11/// <item><see cref="WebApplicationBuilderExtensions.LoadConfiguration"/>, per the command-line <see cref="Parameters"/>
 12/// <item>Controllers, the invalid-model-state envelope (<see cref="ServiceCollectionExtensions.AddInvalidModelStateEnve
 13/// and Swagger (<see cref="WebApplicationBuilderExtensions.AddWebApiSwagger"/>), as tuned by <see cref="WebApiStartupOp
 14/// <item><see cref="ConfigureServices"/>.</item>
 15/// <item>The pipeline: <see cref="ApplicationBuilderExtensions.UseStandardMiddlewares"/> (tracing, exceptions, Swagger,
 16/// CORS, authentication), the extra <see cref="WebApiStartupOptions.Middlewares"/>, then the controllers.</item>
 17/// </list>
 18/// <see cref="Build"/> returns the <see cref="WebApplication"/>, so endpoints beyond the controllers (health checks,
 19/// minimal APIs) are mapped on it before it runs.
 20/// </summary>
 21public abstract class WebApiStartup
 22{
 23    private bool _built;
 24
 25    /// <summary>Parses <paramref name="args"/> and creates the builder, using the standard options.</summary>
 26    /// <param name="args">The command-line arguments passed to the application entry point.</param>
 027    protected WebApiStartup(string[] args) : this(args, _ => { }) { }
 28
 29    /// <summary>Parses <paramref name="args"/> and creates the builder, tuning the standard sequence with
 30    /// <paramref name="configure"/>.</summary>
 31    /// <param name="args">The command-line arguments passed to the application entry point.</param>
 32    /// <param name="configure">Tunes Swagger, CORS, the invalid-model-state envelope and the extra middlewares.</param>
 2033    protected WebApiStartup(string[] args, Action<WebApiStartupOptions> configure)
 34    {
 2035        ArgumentNullException.ThrowIfNull(configure);
 36
 2037        Parameters = new WebApiParameters(args);
 2038        Builder = WebApplication.CreateBuilder(Parameters.ToWebApplicationOptions());
 39
 2040        configure(Options);
 2041    }
 42
 43    /// <summary>The startup parameters parsed from the command-line arguments.</summary>
 6144    protected WebApiParameters Parameters { get; }
 45
 46    /// <summary>The options tuning the standard sequence.</summary>
 15247    protected WebApiStartupOptions Options { get; } = new();
 48
 49    /// <summary>The builder the application is built from. Its environment is
 50    /// <see cref="WebApiParameters.EnvironmentName"/> when one was supplied.</summary>
 13951    protected WebApplicationBuilder Builder { get; }
 52
 53    /// <summary>Registers the application's own services: data access, handlers, token authentication, CORS, hosted
 54    /// services, and so on. Runs after the standard services and before the application is built.</summary>
 55    /// <param name="builder">The builder, exposing <c>Services</c>, <c>Configuration</c> and <c>Environment</c>.</param
 56    protected abstract void ConfigureServices(WebApplicationBuilder builder);
 57
 58    /// <summary>Runs the standard sequence and returns the built application, ready to have further endpoints
 59    /// mapped and to run.</summary>
 60    /// <exception cref="InvalidOperationException">The application was already built.</exception>
 61    public WebApplication Build()
 62    {
 2163        if (_built)
 64        {
 165            throw new InvalidOperationException("The application was already built; Build can be called only once.");
 66        }
 67
 2068        _built = true;
 69
 2070        Builder.LoadConfiguration(Parameters);
 71
 2072        Builder.Services.AddControllers();
 73
 2074        if (Options.UseInvalidModelStateEnvelope)
 75        {
 1976            Builder.Services.AddInvalidModelStateEnvelope();
 77        }
 78
 2079        Builder.AddWebApiSwaggerWith(Parameters, Options.Swagger);
 80
 2081        Builder.Services.Configure<TraceActivityOptions>(trace =>
 2082        {
 1683            trace.LogClientIp = Options.TraceActivity.LogClientIp;
 1684            trace.TagClientAddress = Options.TraceActivity.TagClientAddress;
 3685        });
 86
 2087        ConfigureServices(Builder);
 88
 2089        var app = Builder.Build();
 90
 2091        app.UseStandardMiddlewares(Options.CorsPolicy);
 2092        app.UseWebApiMiddlewares(Options.Middlewares);
 1993        app.MapControllers();
 94
 1995        return app;
 96    }
 97
 98    /// <summary>Builds the application with <see cref="Build"/> and runs it, blocking until it shuts down.</summary>
 099    public void Run() => Build().Run();
 100
 101    /// <summary>Builds the application with <see cref="Build"/> and runs it until it shuts down.</summary>
 0102    public Task RunAsync() => Build().RunAsync();
 103}