KempDec.StarterDotNet 0.13.0

dotnet add package KempDec.StarterDotNet --version 0.13.0
NuGet\Install-Package KempDec.StarterDotNet -Version 0.13.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="KempDec.StarterDotNet" Version="0.13.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add KempDec.StarterDotNet --version 0.13.0
#r "nuget: KempDec.StarterDotNet, 0.13.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install KempDec.StarterDotNet as a Cake Addin
#addin nuget:?package=KempDec.StarterDotNet&version=0.13.0

// Install KempDec.StarterDotNet as a Cake Tool
#tool nuget:?package=KempDec.StarterDotNet&version=0.13.0

StarterDotNet

StarterDotNet é uma biblioteca que fornece utilitários para projetos .NET.

Índice

Instalação

Instale a biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet

Esse pacote incluirá tudo do StarterDotNet, mas você pode optar por instalar apenas uma parte dele. Para isso consulte a seção que deseja.

.NET Reflection

Instalação

Você pode optar por instalar apenas essa parte da biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet.Reflection

Como usar

Você pode usar os métodos de extensão do StarterDotNet Reflection para te ajudar ao usar Reflection do .NET. Exemplo:

Assembly.GetExecutionAssembly()
    .GetAllClassesWithInterface<T>();

Você também pode usar AssemblyHelper para acessar os mesmos métodos de extensão do assembly de Assembly.GetCallingAssembly(). Exemplo:

AssemblyHelper.GetAllClassesWithInterface<T>();

Os métodos de extensão disponíveis são:

// Obtém todas as classes do assembly especificado, se houver alguma, que implemente o tipo da interface especificado.
public static IEnumerable<T?> GetAllClassesWithInterface<T>(this Assembly assembly);

// Obtém todas as classes do assembly especificado, se houver alguma, que implemente o tipo da interface especificado.
public static IEnumerable<T?> GetAllClassesWithInterface<T>(this Assembly assembly, Type interfaceType);

// Obtém os tipos de todas as classes do assembly especificado, se houver alguma, que implemente o tipo da interface
especificado.
public static IEnumerable<Type> GetAllClassesWithInterface(this Assembly assembly, Type interfaceType);

ASP.NET Core Identity

Instalação

Você pode optar por instalar apenas essa parte da biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet.Identity

Como usar

GetPropertyName

Você pode usar a extensão GetPropertyName() para ajudá-lo em validações de erros do ASP.NET Core Identity.

Ele é útil quando você usa um modelo de validação que relaciona o nome da propriedade com o erro, como DataAnnotation ou FluentValidation.

IdentityResult result = await UserManager.CreateAsync(user, _input.Password);

if (!result.Suceeded)
{
    // Neste caso os erros de nome de usuário terão o nome da propriedade como "Email".
    // 
    // As propriedades já tem nomes definidos por padrão que são comumente usados, como os erros de e-mail,
    // que terão o nome da propriedade como "Email" a menos que você mude, assim como acontece abaixo com os
    // erros de nome de usuário.
    var propertyNames = new IdentityErrorPropertiesName(username: nameof(_input.Email));

    foreach (IdentityError error in result.Errors)
    {
        string propertyName = error.GetPropertyName(propertyNames);

        ModelState.AddModelError(propertyName, error.Description);
    }
}
Outras extensões

Os métodos de extensão disponíveis são:

// Determina se o usuário de <see cref="ClaimsPrincipal"/> tem alguma das funções especificadas, separadas por
// vírgula (,).
public static bool IsInRoleNames(this ClaimsPrincipal principal, string roleNames);

Blazor

Instalação

Essa parte da biblioteca deve ser instalada a parte e NÃO está disponível no pacote principal. Instale essa biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet.Blazor

Como usar

JSInterop

Você pode usar StarterJSInterop e JSInteropBase para facilitar a interopabilidade JavaScript do seu aplicativo e executar funções JavaScript a partir do seu código C# no Blazor.

Para isso, crie um arquivo JavaScript contendo as funções que deseja usar com a interopabilidade. No exemplo abaixo o arquivo está localizado em js/app.js.

js/app.js

// Função exportada que será invocada através do módulo.
export function sum(num1, num2)
{
    return num1 + num2;
}

Em seguida crie uma classe que herde StarterJSInterop ou JSInteropBase e importe o seu arquivo JavaScript que deseja usar com a interopabilidade. O exemplo abaixo herda StarterJSInterop por já vir com alguns métodos pré-construídos.

public class AppJSInterop : StarterJSInterop, IAsyncDisposable
{
    private readonly Lazy<Task<IJSObjectReference>> _moduleTask;

    public AppJSInterop(IJSRuntime runtime) : base(runtime) =>
        _moduleTask = ImportModuleFileAsync(moduleFilePath: "js/app.js");

    public override async ValueTask DisposeAsync()
    {
        if (_moduleTask.IsValueCreated)
        {
            IJSObjectReference module = await _moduleTask.Value;

            await module.DisposeAsync();
        }

        await base.DisposeAsync();
    }

    // Interopabilidade com função "console.log" do JavaScript.
    public ValueTask ConsoleLogAsync(string message) => Runtime.InvokeVoidAsync("console.log", message);

    // Interopabilidade com a função "sum" do módulo, que foi exportada do arquivo JavaScript.
    public async ValueTask<int> SumAsync(int num1, int num2)
    {
        IJSObjectReference module = await _moduleTask.Value;

        return await module.InvokeAsync<int>("sum", num1, num2);
    }
}

Adicione a injeção de dependência para AppJSInterop no seu arquivo Program.cs:

builder.Services.AddScoped<AppJSInterop>();

O uso seria semalhante ao exemplo abaixo:

public partial class Home
{
    [Inject]
    private AppJSInterop JS { get; set; } = null!;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        int sumResult = await JS.SumAsync(num1: 1, num2: 2);

        await JS.ConsoleLogAsync(message: $"O resultado da soma é: {sumResult}.");
    }
}

Os métodos disponíveis para StarterJSInterop são:

// Foca em um elemento HTML, se houver algum, que possui o identificador especificado.
public ValueTask FocusOnElementIdAsync(string elementId);

// Habilita um botão, se houver algum, que possui o identificador especificado.
public ValueTask EnableBtnIdAsync(string btnId);

// Desabilita um botão, se houver algum, que possui o identificador especificado.
public ValueTask DisableBtnIdAsync(string btnId);

// Registra a mensagem especificada no console.
public ValueTask ConsoleLogAsync(string message);

// Copia o texto especificado para a área de transferência.
public ValueTask<bool> CopyToClipboardAsync(string text);

// Abre uma nova janela ou guia do navegador com a URL especificada.
public ValueTask OpenAsync(string url);

// Abre uma nova janela ou guia do navegador com a URL especificada.
public ValueTask OpenAsync(string url, IBrowsingContext target);
StarterRenderMode

Use StarterRenderMode para definir a renderização interativamente no servidor por meio da hospedagem do Blazor Server sem pré-renderização do lado do servidor.

Em seu arquivo _Imports.razor adicione:

@using static KempDec.StarterDotNet.Blazor.StarterRenderMode

E então defina o modo de renderização da seguinte maneira:

@rendermode InteractiveServerWithoutPrerendering
Métodos de extensão

Os métodos de extensão disponíveis são:

// Determina se o usuário de <see cref="ClaimsPrincipal"/> em <paramref name="authenticationState"/> tem alguma das
// funções especificadas, separadas por vírgula (,).
public static Task<bool> UserIsInRoleNamesAsync(this Task<AuthenticationState> authenticationState, string roleNames);

// Determina se o usuário de <see cref="ClaimsPrincipal"/> em <paramref name="authenticationState"/> tem alguma
// das funções especificadas, separadas por vírgula (,).
public static Task<bool> UserIsInRoleNamesAsync(this Task<AuthenticationState> authenticationState, string roleNames,
    Func<Task> func);

Métodos de extensão avulsos

Instalação

Você pode optar por instalar apenas essa parte da biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet.Extensions

Métodos disponíveis

Os métodos disponíveis são:

// Substitui o item de formato em uma cadeia de caracteres especificada pela representação de cadeia de caracteres
// de um objeto correspondente em uma matriz especificada.
public static string FormatWith(this string format, params object?[] args);

// Obtém uma saudação com base na hora especificada.
public static string Greeting(this int hour);

// Obtém uma saudação com base na hora do <see cref="DateTime"/> especificado.
public static string Greeting(this DateTime date);

// Lança <see cref="InvalidOperationException"/> quando <paramref name="obj"/> é nulo.
// Esse método é para ser usado somente com propriedades ou campos.
public static void ThrowIfNull(this object? obj, string? propertyOrFieldName = null);

Rotas do aplicativo

Instalação

Você pode optar por instalar apenas essa parte da biblioteca a partir do NuGet.

Install-Package KempDec.StarterDotNet.AppRoutes

Como usar

Você pode usar IAppRoute e AppRouteBase para ajudá-lo a usar as rotas do seu aplicativo.

Eles permitem que você pré-construa as rotas e depois apenas as usem de forma fácil e clara, definindo todos os parâmetros que são necessários e facilitando a manutenção do código caso alguma regra na sua rota mude.

@* Ao invés de: *@
<a href="/profile/@_profile.Id/orderhistory?status=@_orderStatus"></a>
<a href="/start?email=@_email"></a>
<a href="/start?email=@_email&redirectUrl=@_currentUrl"></a>

@* Use algo como: *@
<a href="@AppRoute.Profile.OrderHistory(_profile.Id, _orderStatus)"></a>
<a href="@AppRoute.Start(_email)"></a>
<a href="@AppRoute.Start(_email, _currentUrl)"></a>

Para isso, crie uma rota do aplicativo, de maneira semelhante a abaixo:

// Rota da página /start.
public sealed class StartAppRoute(string? email = null, string? redirectUrl = null) : AppRouteBase("/start")
{
    protected override Dictionary<string, string?> Params { get; } = new()
    {
        { "email", email },
        { "redirectUrl", redirectUrl }
    };
}

// Rota da página /profile/{profileId}/orderhistory.
public sealed class OrderHistoryAppRoute(int profileId, OrderStatusType? orderStatus = null)
    : AppRouteBase("/profile", profileId.ToString(), "orderhistory")
{
    protected override Dictionary<string, string?> Params { get; } = new()
    {
        { "status", orderStatus?.ToString() }
    };
}

// Conjunto de rotas para /profile.
public sealed class ProfilesAppRoute
{
    public OrderHistoryAppRoute OrderHistory(int profileId, OrderStatusType? orderStatus = null) =>
        new(profileId, orderStatus);
}

E então pré-construa as rotas em uma classe estática:

public static class AppRoute
{
    // Rotas para /profile.
    public static ProfilesAppRoute Profile { get; } = new();

    // Rota /start.
    public static StartAppRoute Start(string? email = null) => new(email);
}

Autores

Notas de lançamento

Para notas de lançamento, confira a seção de releases do StarterDotNet.

Licença

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.13.0 111 4/8/2024
0.12.0 86 4/5/2024
0.11.2 87 3/20/2024
0.11.1 112 1/18/2024
0.11.0 113 1/6/2024
0.10.1 88 1/6/2024
0.10.0 101 1/6/2024
0.9.0 127 12/28/2023
0.8.0 103 12/23/2023
0.7.1 90 12/21/2023
0.7.0 85 12/21/2023
0.6.0 121 12/16/2023
0.5.0 119 12/15/2023
0.4.0 125 12/12/2023
0.3.1 137 12/10/2023
0.3.0 114 12/9/2023
0.2.0 155 11/25/2023
0.1.0 128 11/25/2023