Cayaqui.MPS.Metadata 0.4.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Cayaqui.MPS.Metadata --version 0.4.0
                    
NuGet\Install-Package Cayaqui.MPS.Metadata -Version 0.4.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="Cayaqui.MPS.Metadata" Version="0.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cayaqui.MPS.Metadata" Version="0.4.0" />
                    
Directory.Packages.props
<PackageReference Include="Cayaqui.MPS.Metadata" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cayaqui.MPS.Metadata --version 0.4.0
                    
#r "nuget: Cayaqui.MPS.Metadata, 0.4.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.
#:package Cayaqui.MPS.Metadata@0.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cayaqui.MPS.Metadata&version=0.4.0
                    
Install as a Cake Addin
#tool nuget:?package=Cayaqui.MPS.Metadata&version=0.4.0
                    
Install as a Cake Tool

Cayaqui.MPS.Metadata

Zero-dependency attributes + resolver para decorar DTOs con metadata consumida por web grids, Cayaqui.MPS.Reports y Cayaqui.MPS.ExcelImport. Un solo decorado → tres usos consistentes.

Distribución propietaria — requiere contrato comercial con Cayaqui. Ver LICENSE.txt.

v0.4.0 — Enum [Display(Name)] resolution + idempotencia

IExtendedPropertyResolver.Format() ahora resuelve [Display(Name="…")] para valores enum (antes devolvía el identifier C# directo). Esto hace que los componentes de Cayaqui.MPS.Components (MpsAutoGrid, MpsAutoBadge, MpsAutoForm read-only) y los renderers de Cayaqui.MPS.Reports muestren labels localizados.

public enum Status
{
    [Display(Name = "Aprobado")]  Approved,
    [Display(Name = "Rechazado")] Rejected,
}

resolver.Format(Status.Approved, typeof(Row), nameof(Row.Status));
// → "Aprobado" (era "Approved" en 0.3.x)

Cambio aditivo: enums sin [Display] siguen devolviendo value.ToString(). Limitación: enums [Flags] con combinación bit-OR caen al ToString() de .NET ("A, B, C" con identifiers C#) — resolución bit-a-bit es follow-up.

Bug fix idempotencia DI: AddMpsMetadata() y los demás AddMpsX() usan ahora TryAddSingleton/TryAddScoped. Múltiples llamadas (que ocurren cuando otros helpers como AddMpsComponents() lo invocan internamente) no duplican los registros.

Nuevo helper público: EnumExtensions.GetDisplayName() para uso fuera del resolver (charts, chips, código manual).

Instalación

dotnet add package Cayaqui.MPS.Metadata
builder.Services.AddMpsMetadata();  // registra IExtendedPropertyResolver singleton

Ejemplo

public sealed class ControlAccountDto
{
    [Label("Código CA")] [Wbs] [UpperCase]
    [NotEmpty] [MaxLength(20)] [RegularExpression(@"^[A-Z]{2,3}-\d{3,}$")]
    [ImportAlias("Code", "Control Account")]
    public string Code { get; set; } = "";

    [Currency("USD", 2)] [Money] [Align(TextAlign.Right)] [ColumnWidth(140)]
    public decimal Bac { get; set; }

    [Percentage(1)] [EvmIndicator(EvmKind.Cpi)] [EvmBand(green: 0.97, yellow: 0.90)]
    public decimal Cpi { get; set; }

    [Date("dd-MMM-yy")] [Schedule]
    public DateTime ControlDate { get; set; }

    [Badge]   // reads colors from BadgeEnum values
    public ProjectStatus Status { get; set; }

    [Mask(MaskKind.Email, visibleChars: 1)] [Tooltip("Owner email (masked)")]
    public string Owner { get; set; } = "";

    [Hidden]
    public Guid InternalId { get; set; }

    [ImportAlias("SPI", "Schedule Performance Index")]
    [ImportCulture("es-CL")]
    public decimal Spi { get; set; }
}

public enum ProjectStatus
{
    [BadgeColor(BadgeKind.Neutral)]  Draft,
    [BadgeColor(BadgeKind.Info)]     InReview,
    [BadgeColor(BadgeKind.Success)]  Approved,
    [BadgeColor(BadgeKind.Warning)]  OnHold,
    [BadgeColor(BadgeKind.Error)]    Cancelled
}

Los 37 atributos

Display

  • [Label("text")] — override (reuse [Display(Name)] si existe)
  • [Tooltip("text")] — tooltip específico
  • [Placeholder("text")] — placeholder input Blazor
  • Reusar [Display(Name, Description, Order, GroupName)] de DataAnnotations

Format

  • [Currency("USD", 2)]"USD 1,234.56"
  • [Percentage(1)]0.756"75.6%"
  • [Date("dd-MMM-yy")] — formato custom
  • [Integer(thousands: true)]"1,234,567"
  • [DecimalFormat(decimals: 4)]
  • [Duration(DurationUnit.Days)]"5d", "3h", "15m"

Transform (no mutan el valor, sólo el display)

  • [UpperCase] · [LowerCase] · [TitleCase]
  • [Mask(MaskKind.Email, visibleChars: 1)]"a********@cayaqui.com"
  • [Mask(MaskKind.Email, visibleChars: 3)]"ale******@cayaqui.com"
  • [Mask(MaskKind.LastChars, visibleChars: 4)]"******7890"
  • [Truncate(30)]

Layout / Visibility

  • [Align(TextAlign.Right)]
  • [ColumnWidth(150)]
  • [VisibleIn(RenderTargets.Web | RenderTargets.Report)]
  • [Hidden] — shortcut de [VisibleIn(None)]
  • [ReadOnlyDisplay]

Badge

  • [Badge(BadgeKind.Success)] — fijo
  • [Badge] + [BadgeColor(...)] en cada valor del enum — mapeado por valor

Usuario / persona

  • [UserColumn] — marca una prop string como nombre de usuario para que MpsAutoGrid la renderice como <UserChip>. Opcionales:
    • AvatarSource = "SiblingProp" — prop hermana con la URL del avatar.
    • RoleSource = "SiblingProp" — prop hermana con el rol/cargo.
public sealed record AuditRow(
    string Action,
    [property: UserColumn(AvatarSource = "PerformedByAvatar", RoleSource = "PerformedByRole")]
    string PerformedByName,
    string? PerformedByAvatar,
    string? PerformedByRole);

Cayaqui.MPS.Components 0.24+ consume este atributo automáticamente.

Validation (custom shortcuts — reuse DataAnnotations para el resto)

  • [NotEmpty][Required(AllowEmptyStrings = false)]
  • [Min(0)] / [Max(100)] — sugar sobre [Range]
  • Reusar [Required], [MaxLength], [MinLength], [Range], [RegularExpression], [EmailAddress], [Phone], [Url]

EPC dominio

  • [EvmIndicator(EvmKind.Cpi)] — renderer aplica íconos/colores contextuales
  • [EvmBand(green: 0.95, yellow: 0.85)] — thresholds semaforo configurables
  • [Wbs] · [Cbs] · [Schedule] · [Money] — markers semánticos

Import

  • [ImportAlias("CPI", "Cost Performance Index")] — multi-header match
  • [ImportIgnore]
  • [ImportDefault(0)]
  • [ImportCulture("es-CL")] — parsing locale
  • [ImportColumn(3)] — opt-in por posición
  • [ImportTrim(false)] — default true
  • [ImportRegex(@"^[A-Z]+-\d+$")]

API del resolver

public interface IExtendedPropertyResolver
{
    PropertyMetadata? Get(Type dtoType, string propertyName);
    IReadOnlyList<PropertyMetadata> GetAll(Type dtoType);

    /// <summary>
    /// Filtra GetAll() por <see cref="RenderTargets"/> visible (Web | Report |
    /// Excel). Usado por MpsAutoGrid/MpsAutoForm para descartar props
    /// con [VisibleIn] que excluya el target actual.
    /// </summary>
    IReadOnlyList<PropertyMetadata> GetVisibleProperties(Type dtoType, RenderTargets target);

    string? Format(object? value, Type dtoType, string propertyName, CultureInfo? culture = null);
    bool TryParse(string? text, Type dtoType, string propertyName, CultureInfo? culture, out object? value);
}

RenderTargets es un enum bandera (en MPS.Metadata/Models/Enums.cs):

[Flags]
public enum RenderTargets
{
    None   = 0,
    Web    = 1 << 0,   // grids, forms, modals en Blazor
    Report = 1 << 1,   // PDF/Word/PPT vía MPS.Reports
    Excel  = 1 << 2,   // export a XLSX vía MPS.ExcelExport
    All    = Web | Report | Excel,
}

Helper público adicional (v0.4.0+):

namespace MPS.Metadata;
public static class EnumExtensions
{
    /// Devuelve [Display(Name)] del miembro del enum, fallback a ToString().
    public static string GetDisplayName(this Enum value);
}

Cache por Type en primer acceso, thread-safe.

Requisitos

  • .NET 10.0 o superior
  • Zero dependencies externas (sólo Microsoft.Extensions.DependencyInjection.Abstractions para el extension method, que es BCL+)
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on Cayaqui.MPS.Metadata:

Package Downloads
Cayaqui.MPS.Components

Design system and EVM/EPC reusable components (KPI strip, gauges CPI/SPI/PF, S-curves, Gantt, WBS tree grid, R9C, risk heatmap, change orders, purchase orders, engineering deliverables, lookahead grid) for .NET 10 Blazor WebApp (Interactive Server) on top of Syncfusion.Blazor. Proprietary — requires a commercial agreement with Cayaqui.

Cayaqui.MPS.ExcelExport

Exports strongly-typed collections of DTOs to .xlsx using the attributes from Cayaqui.MPS.Metadata: Label for headers, Currency/Percentage/Date for cell formats, Align/ColumnWidth for layout, VisibleIn/Hidden for visibility, Order for column order, Badge for cell background color. Uses Syncfusion XlsIO. Proprietary — requires a commercial agreement with Cayaqui.

Cayaqui.MPS.Reports

Template-based report generation for .NET 10 using Syncfusion File Formats (OpenXML compliant). Supports Excel (XlsIO), Word (DocIO), PowerPoint (Presentation) templates with MailMerge / template markers / placeholder replacement, native chart generation, and PDF conversion. Templates are loaded from Cayaqui.MPS.Storage. Proprietary — requires a commercial agreement with Cayaqui.

Cayaqui.MPS.Storage

Generic storage service for .NET 10 with pluggable providers (Azure Blob Storage, Local File System). Includes streaming upload/download, SAS/file URL generation, container/key model and DI options pattern. Proprietary — requires a commercial agreement with Cayaqui.

Cayaqui.MPS.ExcelImport

Reads .xlsx files and materializes strongly-typed DTOs using the attributes from Cayaqui.MPS.Metadata (ImportAlias, ImportColumn, ImportCulture, ImportDefault, ImportTrim, ImportRegex) plus resolver-based TryParse. Uses Syncfusion XlsIO for spreadsheet access. Proprietary — requires a commercial agreement with Cayaqui.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.17.1 0 5/25/2026
0.17.0 0 5/25/2026
0.4.0 692 5/6/2026
0.3.0 114 5/5/2026
0.2.0 605 4/24/2026
0.1.1 124 4/24/2026
0.1.0 136 4/24/2026

v0.4.0 — IExtendedPropertyResolver.Format ahora resuelve [Display(Name="…")] para valores enum (antes devolvía el identifier C#). Componentes de MPS.Components (MpsAutoGrid, MpsAutoBadge, MpsAutoForm) y renderers de MPS.Reports ahora muestran labels localizados sin código adicional. Cambio aditivo, sin breaking. Limitación: enums [Flags] con combinación bit-OR caen al ToString() de .NET (resolución bit-a-bit es follow-up). Adicional: AddMpsMetadata + AddMpsComponents + 8 helpers más usan TryAdd* — fixea idempotencia DI. Nuevo: EnumExtensions.GetDisplayName() público para uso fuera del resolver.