DS.Foundation.WebApi 8.4.1

dotnet add package DS.Foundation.WebApi --version 8.4.1
                    
NuGet\Install-Package DS.Foundation.WebApi -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.WebApi" 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.WebApi" Version="8.4.1" />
                    
Directory.Packages.props
<PackageReference Include="DS.Foundation.WebApi" />
                    
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.WebApi --version 8.4.1
                    
#r "nuget: DS.Foundation.WebApi, 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.WebApi@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.WebApi&version=8.4.1
                    
Install as a Cake Addin
#tool nuget:?package=DS.Foundation.WebApi&version=8.4.1
                    
Install as a Cake Tool

DS.Foundation.WebApi

Cliente HTTP para consumir APIs REST (en especial los microservicios DS), los contratos de request y response que esas APIs comparten, autorizadores (Bearer, OAuth2 por password, login simple), registro de requests en archivos o memoria, subida de archivos multipart y notificaciones a Slack.

  • Target framework: netstandard2.0 (compatible con Blazor WebAssembly mediante IHttpClient).
  • Dependencias: DS.Foundation, Microsoft.Extensions.Options, System.Text.Json.

Instalación

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

Registro

Los clientes no se registran en DI: se crean con un contexto (WebApiConsumerContext o WebApiClientContext). Cree un contexto por API destino y reutilícelo, porque cada contexto crea su propio HttpClient.

SlackNotifier implementa IApplicationService, pero el paquete no expone un IServiceRepository, así que regístrelo a mano:

using DS.Foundation.WebApi.Notification;

builder.Services.Configure<SlackOptions>(builder.Configuration.GetSection("Slack"));
builder.Services.AddScoped<ISystemNotifier, SlackNotifier>(); // usa IOptionsSnapshot: debe ser scoped

Configuración

WebApiConsumerContext / WebApiClientContext

Propiedad Tipo Valor por defecto Obligatoria
constructor timeout int (segundos) 360 No
BaseUrl string "" Sí (se concatena con el endpoint, sin agregar /)
Authorizer IWebApiAuthorizer null Sí si usa Authentication
Logger IWebApiLogger NopWebApiLogger No
Parameters Dictionary<string,string> vacío No (TENANT-CODE se usa en los logs)
KeepSendRecords / KeepDataRecords bool false No
Authentication (solo WebApiClientContext) WebApiAuthentication (Username, Password) null No
Authorization (solo WebApiClientContext) WebApiAuthorization (Key, Type, AccessToken, ExpiresAt) null No
TimeProvider TimeProvider TimeProvider.System No (reemplazar en pruebas para controlar el vencimiento de los tokens)

Con Authorization cargada, cada request lleva ese encabezado: si Type es Bearer, Authorization: Bearer <AccessToken>; si no, <Key>: <AccessToken>. Si hay Authentication, el request llama a Authorizer.Authorize(usuario, contraseña) cuando todavía no hay token o cuando el token vence en menos de 30 segundos (ExpiresAt), y guarda el token nuevo. WebApiOAuth2Authorizer calcula ExpiresAt a partir de expires_in; un token sin ExpiresAt no vence. Si el login falla no se guarda nada y el request sale sin encabezado de autorización; el siguiente request vuelve a intentar el login.

WebApiClientContext.Clone() copia BagContainer en lugar de compartirlo: use un clon por hilo cuando necesite consumir la misma API en paralelo.

SlackOptions

Propiedad Tipo Valor por defecto Obligatoria
WebhookUrl string "" Sí (sin valor, SendMessage devuelve false)
MaxRetries int 3 No
RetryDelayMilliseconds int 1000 No
TimeoutSeconds int 10 No (límite de cada intento)

SendMessageAsync(mensaje, cancellationToken) no bloquea el hilo; SendMessage es la versión sincrónica. Ambos devuelven false si Slack no responde 200 tras MaxRetries intentos, y como máximo tardan MaxRetries × TimeoutSeconds más las pausas entre intentos.

Uso

Consumir un microservicio DS

using DS.Foundation.WebApi.Authorizer;
using DS.Foundation.WebApi.Client;
using DS.Foundation.WebApi.Security;
using DS.Foundation.WebApi.Surface.Contracts;

var context = new WebApiClientContext(timeout: 60)
{
    BaseUrl = "https://ventas.ejemplo.com",
    Authentication = new WebApiAuthentication { Username = usuario, Password = contraseña },
};
context.Authorizer = new WebApiBearerAuthorizer(context, "/api/identity/sign-in");

var client = new WebApiClient<ResponseContract<List<PedidoDto>>>(context);
ResponseContract<List<PedidoDto>> respuesta = client.SendAsJson("/api/pedidos", "GET");
if (respuesta.Success) { var pedidos = respuesta.Data; }

WebApiClient<T> es sincrónico y tiene puntos de extensión virtuales (DoBeforeExecute, DoAfterExecute, DoBeforeDeserialization, DoAfterDeserialization, FiltrarDatos, CurarDatos).

Llamada asincrónica

using DS.Foundation.WebApi.Consumer;

var consumer = new WebApiConsumer<ResponseContract<PedidoDto>>(context);
var pedido = await consumer.SendAsJsonAsync(new WebApiRequest("/api/pedidos/1", "GET"), cancellationToken);

WebApiConsumer<T> propaga las excepciones de red. La respuesta se deserializa con System.Text.Json sin opciones: los nombres de propiedad distinguen mayúsculas y minúsculas.

Contratos

  • BaseResponseContract: Success, Message, Messages (UserMessageContract). ResponseContract<T> agrega Data.
  • RequestContract<T>: Data más datos de la máquina y la sesión (BaseRequestContract).
  • SearchContract (Id, Code, Text, Include*, Filters), ExtractContract (BatchSize, BatchNumber) y ErrorContract.
  • response.FillWithAppEvent(appEvent) completa Message y Messages desde un AppEvent de DS.Foundation.

Registro de requests

context.Logger = new FileSystemWebApiLogger(@"C:\logs\webapi"); // un JSON por request: <ruta>/<tenant>/<yyyy_MM_dd>/<endpoint>/

MemoryWebApiLogger guarda los eventos en memoria (para depuración) y admite requests concurrentes.

Si el logger lanza una excepción, se ignora: un fallo de registro no hace fallar el request.

Errores frecuentes

Síntoma Causa Solución
ArgumentNullException en WebApiClient<T>.SendAsJson El request falló (red, timeout, DNS): WebApiClient registra el error en el logger y devuelve contenido null, que no se puede deserializar Revisar el logger del contexto; usar WebApiConsumer<T>.SendAsJsonAsync si necesita la excepción original
JsonException al deserializar La respuesta no es JSON (por ejemplo, una página de error HTML) o no coincide con T Verificar el endpoint y el tipo de respuesta
401 con Authentication cargada El login falló: el autorizador devuelve un token vacío sin lanzar excepción y el request sale sin autorización Verificar las credenciales y el endpoint del autorizador
InvalidOperationException: ... no Authorizer Hay Authentication pero Authorizer es null Configurar Authorizer
URL mal formada BaseUrl y el endpoint se concatenan sin separador Terminar BaseUrl sin / y comenzar el endpoint con /

Qué no hacer

  • No usar FileSystemWebApiLogger ni MemoryWebApiLogger en producción con datos sensibles: guardan encabezados y cuerpos completos, incluido el encabezado Authorization y la contraseña enviada al autorizador.
  • No reutilizar un WebApiClientContext durante mucho tiempo con WebApiClient: cada respuesta se agrega a BagContainer y la memoria crece sin límite.
  • No crear un contexto por request: cada contexto crea un HttpClient nuevo.
  • No llamar a los métodos sincrónicos (SendAsJson, Send, Execute, HttpDataFileUploader.Send) desde código asincrónico de ASP.NET Core: bloquean el hilo. Use SendAsJsonAsync.

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 (2)

Showing the top 2 NuGet packages that depend on DS.Foundation.WebApi:

Package Downloads
HQS.DataBridge.Foundation

Package Description

HQS.DataBridge.ERP.DB.Wrapper.Interfaces

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.4.1 188 10/19/2026
8.4.0 100 10/19/2026
8.3.2 141 10/8/2026
8.3.1 349 5/31/2026
8.2.6 811 4/7/2026
8.2.5 324 12/23/2025
8.2.4 273 10/5/2025
8.2.3 237 10/3/2025
8.2.2 362 9/19/2025
8.2.1 492 8/22/2025
8.2.0 474 6/22/2025
8.1.32 264 7/15/2025
8.1.31 285 7/3/2025
8.1.30 403 6/8/2025
8.1.29 264 6/6/2025
8.1.28 215 6/6/2025
8.1.27 257 5/25/2025
8.1.26 323 4/15/2025
8.1.25 275 4/1/2025
8.1.24 358 3/6/2025
Loading failed