DS.Foundation 8.4.1

dotnet add package DS.Foundation --version 8.4.1
                    
NuGet\Install-Package DS.Foundation -Version 8.4.1
                    
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="DS.Foundation" Version="8.4.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DS.Foundation" Version="8.4.1" />
                    
Directory.Packages.props
<PackageReference Include="DS.Foundation" />
                    
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 DS.Foundation --version 8.4.1
                    
#r "nuget: DS.Foundation, 8.4.1"
                    
#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 DS.Foundation@8.4.1
                    
#: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=DS.Foundation&version=8.4.1
                    
Install as a Cake Addin
#tool nuget:?package=DS.Foundation&version=8.4.1
                    
Install as a Cake Tool

DS.Foundation

Núcleo de las librerías DS.Foundation: clases de opciones compartidas (SystemOptions, ApplicationOptions, integración de datos), registro de servicios por escaneo de ensamblados, mensajes de usuario y eventos de aplicación, una base para procesos de integración de datos (extracción, transformación y carga) y utilidades (colas, rangos de fechas, conversión de textos, recursos embebidos, ejecución de comandos).

Úselo como dependencia común de las aplicaciones y de los demás paquetes DS.Foundation.*. Los paquetes de dominio (Data, WebApi, Authentication, etc.) lo referencian.

  • Target framework: netstandard2.0.
  • Dependencias: Microsoft.Extensions.Configuration, Microsoft.Extensions.Logging.Abstractions y Microsoft.Extensions.Options.

Instalación

<PackageReference Include="DS.Foundation" Version="8.4.1" />

Registro

AddFoundationServices y AddApplicationServices recorren los ensamblados de los objetos IServiceRepository recibidos y registran como scoped cada clase que implementa IFoundationService o IApplicationService, respectivamente. Cada clase se registra por su tipo concreto, no por sus interfaces.

using DS.Foundation.Services;
using DS.Foundation.Services.Extensions;

builder.Services.AddFoundationServices(new IServiceRepository[]
{
    new DS.Foundation.Services.ServiceRepository(),                 // DsCryptographyService, SystemDateTimeProviderService
    new DS.Foundation.Authentication.Services.ServiceRepository(),  // si usa DS.Foundation.Authentication
});

// Servicios propios: cualquier clase de su ensamblado que implemente IApplicationService.
builder.Services.AddApplicationServices(new IServiceRepository[] { new MiApp.ServiceRepository() });

Para que su ensamblado sea escaneado, declare una clase vacía que implemente IServiceRepository:

namespace MiApp
{
    public class ServiceRepository : DS.Foundation.Services.IServiceRepository { }
}

Las clases de opciones (SystemOptions, ApplicationOptions, etc.) no se registran solas: la aplicación las enlaza con el patrón Options.

builder.Services.Configure<SystemOptions>(builder.Configuration.GetSection("System"));

// Obligatorio si la aplicación resuelve DsCryptographyService (ver Configuración).
builder.Services.Configure<CryptographyOptions>(builder.Configuration.GetSection(CryptographyOptions.SectionName));

Configuración

SystemOptions

Propiedad Tipo Valor por defecto Obligatoria
Code string "" Sí, si usa CookieName
Name string "" No
Environment string "DEFAULT" No
Scheduler SchedulerOptions (Enable: bool) instancia vacía No
Application ApplicationOptions instancia vacía No
Services Dictionary<string, ServiceOptions> (Code, Name, BaseUrl) vacío No
CookieName string (solo lectura) Code + "-USR-SID" -

ApplicationOptions

Propiedad Tipo Valor por defecto Obligatoria
Code string "" No
Name string "" No
Settings List<SettingOptions> (Key, Value) vacía No
DataStore DataStoreOptions instancia vacía No

DataStoreOptions (integración de datos)

Propiedad Tipo Valor por defecto Obligatoria
Type DataStoreTypeEnum (Database, FileSystem, SecureFtp, RestApi, SoapWebService, DataLaneContext) Database Sí
Host string "" Según el tipo
Port int 0 Según el tipo
Path string "" Según el tipo (en bases de datos, el nombre de la base)
IsPathDirectory bool false No
Filter string "" No
Timeout int (segundos) 30 No
Security DataSecurityOptions (usuario, contraseña, API key, client id/secret, Workspaces) instancia vacía Según el tipo

DataLaneOptions → DataTaskOptions → DataStepOptions describen la jerarquía carril → tarea → paso. Cada nivel tiene Code, Name, Type, Order y Enabled. Cada paso tiene Source y Destination (DataStoreOptions).

SystemDateTimeProviderService

Lee la clave System:Date de IConfiguration en el constructor.

Clave Valores Obligatoria
System:Date "TODAY" o "HOY": GetNow() devuelve DateTime.Now. Una fecha yyyy-MM-dd: GetNow() devuelve esa fecha con la hora actual (útil para pruebas). No: si falta o está vacía, se usa la fecha actual.

GetNow() devuelve hora local del servidor (DateTime.Kind = Local), no UTC.

DsCryptographyService

Cifra y descifra textos con AES (Rijndael, clave de 256 bits) y calcula hashes SHA1. Recibe IOptions<CryptographyOptions> y no lee IConfiguration.

La aplicación que usa DS.Foundation debe cargar CryptographyOptions. No hay valores por defecto: si falta Key o InitializationVector, o alguno es inválido, el constructor lanza InvalidOperationException (el mensaje indica la propiedad) y el servicio no se puede resolver, ni siquiera para CreateHash.

Propiedad Valor Obligatoria
CryptographyOptions.Key 32 bytes en hexadecimal (64 caracteres) Sí
CryptographyOptions.InitializationVector 16 bytes en hexadecimal (32 caracteres) Sí

Desde una sección de configuración (CryptographyOptions.SectionName es "System:Cryptography"; puede usar otra):

using DS.Foundation.Configuration.Options;

builder.Services.Configure<CryptographyOptions>(
    builder.Configuration.GetSection(CryptographyOptions.SectionName));

O con valores que la aplicación obtiene de otra fuente (por ejemplo, un almacén de secretos):

builder.Services.Configure<CryptographyOptions>(o =>
{
    o.Key = secretos.ObtenerClave();
    o.InitializationVector = secretos.ObtenerIV();
});

Cargue los valores desde variables de entorno (System__Cryptography__Key, System__Cryptography__InitializationVector) o un almacén de secretos, nunca desde un appsettings.json versionado. Para generarlos: Bytes.ByteArrayToHex(Bytes.GenerateKey()) y Bytes.ByteArrayToHex(Bytes.GenerateIV()) (DS.Foundation.Security.Cryptography.Effortless). Si cambia la clave, lo que se cifró con la anterior ya no se puede descifrar con el servicio.

Migración desde versiones anteriores a 8.4.0: esas versiones cifraban siempre con la clave y el IV por defecto que traía CryptographyOptions en DS.Foundation 8.3.2, y que ya no existen. Para seguir descifrando esos datos, cargue temporalmente esos valores (están en CryptographyOptions.cs de la versión 8.3.2). Son públicos, así que descifre los datos existentes y vuelva a cifrarlos con una clave propia.

Uso

Mensajes de usuario y eventos de aplicación

using DS.Foundation.Security;
using DS.Foundation.UserMessage;

public class MensajeDeUsuario : IUserMessage
{
    public string Code { get; set; } = "";
    public string Caption { get; set; } = "";
    public string Text { get; set; } = "";
    public string Type { get; set; } = "";
}

public class MensajesDeVentas : UserMessageSourceBase
{
    public MensajesDeVentas()
    {
        Add(new MensajeDeUsuario { Code = "VTA-001", Caption = "Ventas", Text = "El cliente no existe.", Type = "ERROR" });
    }
}

var repositorio = new UserMessageRepository();
repositorio.AddSource(new MensajesDeVentas());

var eventos = new AppEventFactory(repositorio);
AppEvent evento = eventos.Create("usuario", "VTA-001");

AppEvent puede completar un contrato de respuesta con FillWithAppEvent (paquete DS.Foundation.WebApi).

Integración de datos

DataLaneService, DataTaskService y DataStepService son clases base abstractas.

  • Setup guarda el contexto y, si DataLaneContext.WorkingDirectory está vacío, crea un directorio temporal nuevo y lo asigna.
  • DataTaskService.Execute() llama a Extract(), Transform() y Load() en ese orden. Cada uno toma de options.Steps el único paso con Type "E", "T" o "L" y lo ejecuta con el DataStepService correspondiente.
  • La clase derivada debe asignar los campos protegidos extractor, transformer y loader antes de Execute().

Utilidades

var cola = new SmartQueue<int>(Enumerable.Range(1, 1000));
IList<int> lote = cola.Dequeue(100);            // hasta 100 elementos

using (var cmd = new RunCmd("git", "status"))
{
    int exitCode = cmd.Execute();   // espera a que termine; -1 si no pudo iniciarse
    string salida = cmd.GetOutput(); // salida estándar; la de errores se descarta
}

DateTimeRange hoy = DateTimeRange.GetTodayDateTimeRange();
DateTimeRange semana = DateTimeRange.GetThisWeekDateTimeRange(); // lunes 00:00:00 a domingo 23:59:59
string base64 = StringCodeConverter.ToBase64("texto");

// Seguro entre hilos; guarda hasta n - 1 elementos y Poner devuelve false si está lleno.
var buffer = new BufferProductorConsumidor<string>(n: 100, k: 10);
buffer.Poner("evento");
string[] loteDeDiez = buffer.Sacar();   // 10 elementos, o vacío si todavía hay menos de 10
string[] resto = buffer.SacarTodos();

Cifrado TripleDES con Cryptography

byte[] key = ...; // 16 o 24 bytes, desde configuración o un almacén de secretos
byte[] iv = ...;  // 8 bytes
string cifrado = Cryptography.Encrypt256("texto", key, iv);
string texto = Cryptography.Decrypt256(cifrado, key, iv);

Encrypt256 y Decrypt256 usan TripleDES (bloques de 64 bits, CBC, PKCS7); el "256" del nombre se conserva por compatibilidad. Lanzan ArgumentException si la clave no tiene 16 o 24 bytes o el IV no tiene 8, y CryptographicException si la clave es débil o, al descifrar, no coincide.

Errores frecuentes

Síntoma Causa Solución
KeyNotFoundException en UserMessageRepository.Get o AppEventFactory.Create Ningún origen registrado contiene el código Registrar el origen con AddSource o corregir el código
InvalidOperationException en DataTaskService.Execute Falta un paso "E", "T" o "L", o hay más de uno del mismo tipo Definir exactamente un paso de cada tipo
NullReferenceException en DataTaskService.Execute La clase derivada no asignó extractor, transformer o loader Asignarlos en el constructor o en Setup
Un servicio no se resuelve por su interfaz AddFoundationServices/AddApplicationServices registran el tipo concreto Inyectar la clase concreta o registrar la interfaz manualmente
NotSupportedException en Cryptography.Encrypt256(string)/Decrypt256(string) Las versiones sin clave están obsoletas y no funcionan Usar Encrypt256(text, key, iv)/Decrypt256(text, key, iv)
InvalidOperationException al resolver DsCryptographyService La aplicación no cargó CryptographyOptions.Key o InitializationVector, o el valor no es hexadecimal o no tiene 32/16 bytes. El mensaje indica la propiedad Cargar ambos valores con services.Configure<CryptographyOptions>(...) (ver DsCryptographyService)
CryptographicException en DsCryptographyService.Decrypt El texto se cifró con otra clave o IV (por ejemplo, con los valores por defecto de una versión anterior a 8.4.0) Descifrar con la clave original y volver a cifrar con la nueva

Qué no hacer

  • No cargar en CryptographyOptions la clave y el IV de versiones anteriores a 8.4.0 salvo para migrar datos antiguos: son públicos. DsCryptographyService.CreateHash usa SHA1, y los helpers MD5 de Cryptography tampoco sirven para contraseñas.
  • No escribir en el código la clave ni el IV de Cryptography.Encrypt256/Decrypt256.
  • No confiar en AddMapsterTypeAdapters: no realiza ningún registro (se conserva por compatibilidad).
  • Los métodos de DateTimeRange usan DateTime.Now (hora local del servidor).
  • No guardar en SystemOptions ni en DataSecurityOptions secretos en appsettings.json versionado: use variables de entorno o un almacén de secretos.

Cambios

Ver CHANGELOG.md.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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 DS.Foundation:

Package Downloads
DS.Foundation.WebApi

Cliente HTTP, consumidores Web API, contratos y logging.

DS.Foundation.Authentication

JWT, tokens y validación de API key (sin integración ASP.NET Core).

DS.Foundation.Data

Acceso a datos, DbManagers multi-motor y FluentMigrator.

DS.Foundation.NHibernate

Package Description

DS.Foundation.Data.Tactica

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.4.1 364 10/19/2026
8.4.0 308 10/19/2026
8.3.3 246 10/8/2026
8.3.2 466 6/10/2026
8.3.1 551 5/31/2026
8.2.9 157 5/28/2026
8.2.8 214 5/28/2026
8.2.7 178 5/18/2026
8.2.6 1,259 1/7/2026
8.2.5 457 10/5/2025
8.2.4 324 10/3/2025
8.2.3 410 9/19/2025
8.2.2 587 8/19/2025
8.2.1 809 6/25/2025
8.2.0 762 6/22/2025
8.1.30 368 9/19/2025
8.1.29 249 7/18/2025
8.1.28 385 7/3/2025
8.1.27 489 5/25/2025
8.1.26 684 4/15/2025
Loading failed