DEV Community

Cover image for dotnet Framework life cycle tool
Karen Payne
Karen Payne

Posted on

dotnet Framework life cycle tool

Introduction

Learn how to create a dotnet Global Tool that lists all NET Core Frameworks with release and end-of-life information.

💡 For my other article on creating various dotnet tools see
C# .NET Tools with System.CommandLine.

This tool is extremely simple: unlike most tools, there are no required arguments or help; the code reads information from the following URL and displays it.

SCREENSHOT

Main code

Core Source code

Located in CommonLibrary project

using CommonLibrary.Models;
using System.Text.Json;

namespace CommonLibrary;

public static class DotNetReleaseService
{
    private static readonly HttpClient _httpClient = new();

    public static async Task<List<ReleaseIndexItem>> GetReleaseIndexAsync(CancellationToken cancellationToken = default)
    {
        const string url = "https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json";

        using HttpResponseMessage response = await _httpClient.GetAsync(url, cancellationToken);
        response.EnsureSuccessStatusCode();

        await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);

        var root = await JsonSerializer.DeserializeAsync<ReleasesIndexRoot>(
            stream,
            Options,
            cancellationToken);

        return root?.ReleasesIndex ?? [];
    }


    public static JsonSerializerOptions Options 
        => new() { PropertyNameCaseInsensitive = true };
}


public sealed class ReleaseIndexItem
{
    [JsonPropertyName("channel-version")]
    public string? ChannelVersion { get; set; }

    [JsonPropertyName("latest-release")]
    public string? LatestRelease { get; set; }

    [JsonPropertyName("latest-release-date")]
    public DateTime? LatestReleaseDate { get; set; }

    [JsonPropertyName("security")]
    public bool Security { get; set; }

    [JsonPropertyName("latest-runtime")]
    public string? LatestRuntime { get; set; }

    [JsonPropertyName("latest-sdk")]
    public string? LatestSdk { get; set; }

    [JsonPropertyName("product")]
    public string? Product { get; set; }

    /// <summary>
    /// Gets or sets the support phase of the release.
    /// </summary>
    /// <remarks>
    /// The support phase indicates the current lifecycle stage of the release, 
    /// such as "active", "preview", or "eol" (end of life).
    /// </remarks>
    [JsonPropertyName("support-phase")]
    public string? SupportPhase { get; set; }

    [JsonPropertyName("eol-date")]
    public DateTime? EndOfLifeDate { get; set; }

    [JsonPropertyName("release-type")]
    public string? ReleaseType { get; set; }

    [JsonPropertyName("releases.json")]
    public string? ReleasesJsonUrl { get; set; }
}


public sealed class ReleasesIndexRoot
{
    [JsonPropertyName("releases-index")]
    public List<ReleaseIndexItem>? ReleasesIndex { get; set; }

Enter fullscreen mode Exit fullscreen mode

Entry point code

Source code

using CommonLibrary;
using Spectre.Console;
using SpectreConsoleLibrary.Core;
using System.CommandLine;

namespace FrameworkLifeCycle;

internal partial class Program
{
    static async Task Main(string[] args)
    {
        RootCommand rootCommand = new("Get dotnet framework life cycles");

        var releases = await DotNetReleaseService.GetReleaseIndexAsync();

        SpectreConsoleHelpers.InfoPill(Justify.Left, $"Found {releases.Count} releases.");
        Console.WriteLine();

        var table = new Table().Title("[bold blue] .NET Release Information [/]");
        table.AddColumn(new TableColumn("[bold yellow]Channel[/]"));
        table.AddColumn(new TableColumn("[bold yellow]Latest[/]"));
        table.AddColumn(new TableColumn("[bold yellow]ReleaseType[/]"));
        table.AddColumn(new TableColumn("[bold yellow]End Of Life Date[/]"));
        table.AddColumn(new TableColumn("[bold yellow]Support[/]"));

        foreach (var item in releases)
        {

            var eolText = item.EndOfLifeDate.HasValue
                ? item.EndOfLifeDate.Value.ToString("MM/dd/yyyy")
                : "Not set";

            var releaseType = item.ReleaseType ?? "Unknown";
            if (releaseType != "Unknown")
            {
                releaseType = releaseType.ToUpper();
            }

            table.AddRow(
                FrameworkUtilities.IsProjectFramework(item.ChannelVersion ?? ""),
                item.LatestRelease ?? "",
                releaseType,
                eolText,
                Colorize(item.SupportPhase ?? "Unknown"));
        }

        AnsiConsole.Write(table);
        Console.WriteLine();

    }

    private static string Colorize(string input) =>
        input switch
        {
            { } s when s.Contains("active", StringComparison.OrdinalIgnoreCase) => "[green]Active[/]",
            { } s when s.Contains("eol", StringComparison.OrdinalIgnoreCase) => "[red]eol[/]",
            { } s when s.Contains("preview", StringComparison.OrdinalIgnoreCase) => "[yellow]preview[/]",
            _ => input,
        };
}
Enter fullscreen mode Exit fullscreen mode

Project file

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>flc</ToolCommandName>
    <PackageOutputPath>./nupkg</PackageOutputPath>
    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
    <Version>1.0.0</Version>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode
  • PackAsTool Indicate this as a dotnet tool
  • ToolCommandName the command to run as at the command line
  • PackageOutputPath Path to binaries

Summary

Once installed, typing flc will list all dot net Framework life cycles and for many developers be their first useful donet tool.

💡 For my other article on creating various dotnet tools, see
C# .NET Tools with System.CommandLine, which shows how to work with arguments and provide help.

Top comments (0)