El SDK de Dinaup para .NET te permite conectar tus aplicaciones directamente con la plataforma Dinaup.
Esta guía explica, paso a paso, cómo usar el SDK de Dinaup en .NET para conectarte al servicio, consultar informes, gestionar archivos, añadir anotaciones, generar documentos dinámicos, leer/escribir datos de secciones y trabajar con paginación y filtros.
var client =awaitDinaupClientC.ConnectAsync( endPoint:"https://api.dinaup.com/v2/tu-codigo", publicKey:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", secretKey:"tu-secret-key-aqui");if(client ==null||client.IsConnected==false){thrownewException("No se pudo conectar a Dinaup");}
usingDinaup;// Las unicas credenciales en variables de entornovar vault =newVaultData(Environment.GetEnvironmentVariable("VAULT_URL"),Environment.GetEnvironmentVariable("VAULT_PASSWORD"));vault.Initialize();// Todo lo demas viene del Vaultvar client =awaitDinaupClientC.ConnectAsync( endPoint:vault.Read("dinaup.endpoint"), publicKey:vault.Read("dinaup.publickey"), secretKey:vault.Read("dinaup.secretkey"));if(client ==null||client.IsConnected==false){thrownewException("No se pudo conectar a Dinaup");}
3
Opera
// Use pre-built reports from DemoUp.MyDinaupusingDemoUp.MyDinaup.Reports.FuncionalidadD;// Create and execute the reportvar ventasReport =newAPIVentasC();awaitventasReport.ExecuteQueryAsync( dinaupClient: client, page:1, resultsPerPage:50);// Access resultsConsole.WriteLine($"Total: {ventasReport.TotalResults} records");foreach(var row inventasReport.Rows){Console.WriteLine($"- {row.NumerodefacturaCompleto}: {row.Total}");}
Guid sectionId =/* sección destino */;var data =newDictionary<string,string>{{SeccionDePruebasAPIES.TextoPrincipal,$"Prueba {Guid.NewGuid()}"}};var wOp =newWriteOperation("", data);// "" => altavar result=dinaupClient.RunWriteOperation(dinaupClient.DefaultSession,SeccionDePruebasAPIES.SectionId, wOp,false);// Lanza excepción si hubo errores globalesresult.EnsureSuccess();Guid newId =wOp.WriteOperationResult.RowID;
Referencias
Dinaup .NET
Antes de empezar necesitarás instalar el paquete Dinaup, que incluye el Cliente base: conexión, autenticación, sesiones, archivos, anotaciones, WriteOperations, etc.
Dinaup es una plataforma flexible: cada empresa cuenta con su propio modelo de datos (secciones, informes y documentos dinámicos). Para trabajar de forma tipada con ese modelo, necesitas la biblioteca MyDinaup específica de tu organización. MyDinaup incluye modelos y utilidades tipadas (Reports, SectionsD y DynamicDocuments) con los nombres reales de tus secciones y depende del paquete base Dinaup.
Modelo Ready to Go
Este Nuget únicamente incluye la modelización de la estructura Ready to Go. Ideal para desarrollos compatibles con varias empresas.
Este es un modelo de Pre-Producción que utiliza internamente el equipo de Dinaup. Su uso está desaconsejado ya que puede contener errores y estructuras incompatibles.
Los archivos en PublicGallery son públicos: cualquiera con el enlace puede verlos.
A continuación, ejemplos usando AnnotationTypeE.Comments.
Agregar un comentario (solo texto)
Agregar un comentario con archivo adjunto
Leer anotaciones
Documentos dinámicos
Los Documentos Dinámicos permiten:
Agrupar varias consultas en una sola operación para reducir latencia.
Generar documentos de impresión (facturas, albaranes) delegando la composición en Dinaup.
Recomendación:
Para consultar datos en general, usa Reports siempre que sea posible. Documentos Dinámicos son útiles para orquestar múltiples consultas y componer resultados.
Ejecutar un documento dinámico
Secciones
Las secciones son el equivalente a tablas/entidades por empresa (Clientes, Facturas, Empleados, etc.). En MyDinaup existen utilidades tipadas para trabajar con ellas:
Espacio de nombres: MyDinaup.SectionsD
Incluye métodos para leer registros por Id o por criterios.
Advertencia de rendimiento:
Las operaciones de lectura en SectionsD consultan todos los datos de la sección y los textos principales de los datos relacionados (p. ej., en una venta también recupera empleados, clientes, productos, impuestos, etc.). Esto tiene mayor coste computacional.
Para rendimiento óptimo, usa Reports. Para escenarios “super optimizados”, usa PGSync.
Usa SectionsD cuando el código se ejecute con poca frecuencia o para prototipos rápidos.
Recibir un dato por Id
Recibir una lista
Escritura
Las operaciones de escritura usan WriteOperation para altas y ediciones.
El ID vacío ("") indica alta
Un ID válido indica edición.
Un ID que no existe provocará una excepción.
Alta simple (crear un registro)
Edición (actualizar un registro existente)
Alta 10 registros de golpe
Editar 10 registros
Si se vana procesar más de 20 registros, usa .Chunk(20) para dividir en bloques.
La escritura virtualizada permite que Dinaup ejecute automáticamente la lógica de negocio definida en una sección. Al activarla, cualquier operación de escritura se comporta como si se hubiera realizado desde la interfaz web: con scripts, validaciones, eventos, y cálculos incluidos.
¿Qué hace la virtualización?
Cuando se activa la virtualización en una operación de escritura (RunWriteOperationAsync con virtualized: true), Dinaup:
Ejecuta scripts personalizados de la sección (onBeforeSave, onAfterSave, etc.)
Cuando se desactiva (virtualized: false), simplemente se guardan los valores tal como se reciben (Creando histórico). No se ejecuta ningún comportamiento adicional.
La escritura virtualizada es más costosa en términos de rendimiento.
Cada operación implica ejecutar scripts del backend y lógica personalizada, lo que puede afectar la velocidad si estás procesando muchos registros o usas esta opción innecesariamente.
¿Cuándo usar virtualización?
✅ Usa escritura virtualizada cuando la sección contiene lógica de negocio activa que debe ejecutarse. Esto incluye cálculos automáticos de totales en ventas, generación de fechas de vencimiento, o scripts que actualizan otras entidades relacionadas. Por ejemplo, al registrar una nueva venta, al cerrar un pedido o al generar una factura, la virtualización asegura que todo se procese correctamente.
¿Cuándo evitar virtualización?
⛔ Evita la virtualización cuando realizas modificaciones simples que no requieren ejecutar lógica adicional. Esto incluye acciones como cambiar el estado de una venta, asignar un técnico a un ticket de soporte, registrar una nota interna o marcar una tarea como completada. En estos casos, desactivarla mejora el rendimiento sin afectar el comportamiento esperado.
using Dinaup;
var builder = WebApplication.CreateBuilder(args);
// Cargar Vault
var vault = new VaultData(
Environment.GetEnvironmentVariable("VAULT_URL"),
Environment.GetEnvironmentVariable("VAULT_PASSWORD")
);
vault.Initialize();
// Conectar a Dinaup
var client = await DinaupClientC.ConnectAsync(
endPoint: vault.Read("dinaup.endpoint"),
publicKey: vault.Read("dinaup.publickey"),
secretKey: vault.Read("dinaup.secretkey")
);
if (client == null || client.IsConnected == false)
throw new Exception("No se pudo conectar a Dinaup");
// Registrar como Singleton
builder.Services.AddSingleton(client);
var app = builder.Build();
Guid rowId = /* Id del registro a editar */;
var data = new Dictionary<string, string>
{
{
SeccionDePruebasAPIES.TextoPrincipal,
$"Prueba {Guid.NewGuid()}"
}
};
var wOp= new WriteOperation(rowId, data);
var result= dinaupClient.RunWriteOperation(
dinaupClient.DefaultSession,
sectionId,
wOp,
false
);
// Lanza excepción si hubo errores globales
result.EnsureSuccess();
Guid updatedId = wOp.WriteOperationResult.RowID;
using DemoUp.MyDinaup.Reports.FuncionalidadD;
var report = new APISeccionDePruebasAPIC(); //
await report.ExecuteQueryAsync(dinaupClient, page: 1, pageSize: 10);
Console.WriteLine($"Total resultados: {report.TotalResults}");
if (report.Rows.IsNotEmpty())
{
foreach (var fila in report.Rows)
{
// Accede a propiedades tipadas de cada fila
// Ej.: fila.TextoPrincipal, fila.ValorEntero, etc.
}
}
var report = new APISeccionDePruebasAPIC();
// Igualdad estricta
report.AddFilter(
SeccionDePruebasAPIES.ValorEntero,
"=",
3);
await report.ExecuteQueryAsync(dinaupClient, page: 1, pageSize: 10);
if (report.Rows.IsNotEmpty())
{
foreach (var fila in report.Rows)
{
// Usar fila...
}
}
// Clave de relación (ruta compuesta)
var relationKey =
SeccionDePruebasAPIES._SectionID.STR() + "." +
SeccionDePruebasAPIES.ReferenciaAutorDelAlta + "." +
EntidadesBaseES._SectionID.STR() + "." +
EntidadesBaseES.VIP;
var report = new APISeccionDePruebasAPIC();
report.AddFilter(relationKey, "=", 3);
await report.ExecuteQueryAsync(dinaupClient, page: 1, pageSize: 10);
if (report.Rows.IsNotEmpty())
{
foreach (var fila in report.Rows)
{
// Usar fila...
}
}
// Between (ej.: 1 a 2999)
var reportBetween = new APISeccionDePruebasAPIC();
reportBetween.AddFilterBetween(
SeccionDePruebasAPIES.ValorEntero,
1,
2999
);
await reportBetween.ExecuteQueryAsync(dinaupClient, page: 1, pageSize: 10);
var eventosReport = new APIEventosDeCRMC();
var campoInicio = EventosDeCRMES.InicioEvento_UTC;
var campoFin = EventosDeCRMES.FinEvento_UTC;
var rangoInicio = DateOnly.FromDateTime(new DateTime(2000, 1, 1));
var rangoFin = DateOnly.FromDateTime(DateTime.Today.AddYears(50));
eventosReport.AddFilterDateRangeOverlapFilter(campoInicio, campoFin, rangoInicio, rangoFin);
await eventosReport.ExecuteQueryAsync(dinaupClient, page: 1, pageSize: 25);
var report = new APISeccionDePruebasAPIC();
await report.ExecuteQueryAsync(_dinaupClient, 1, 300);
if (report.Rows.IsNotEmpty())
{
do
{
foreach (var row in report.Rows)
{
}
} while (await report.ExecuteQuery_NextPageAsync());
}
var bytes = System.Text.Encoding.UTF8.GetBytes("hola " + Guid.NewGuid());
var upload = await dinaupClient.File_UploadBytesAsync(
dinaupClient.DefaultSession,
bytes,
"prueba.txt"
);
Guid fileId = upload.FileId;
Guid sectionId = /* tu sección */;
Guid rowId = /* registro al que agregas el comentario */;
await dinaupClient.Annotation_PutAsync(
dinaupClient.DefaultSession,
sectionId,
rowId.STR(),
Guid.Empty, // sin archivo adjunto
"¡Hola mundo! Este es mi primer comentario.",
AnnotationTypeE.Comments
);
var bytes = System.Text.Encoding.UTF8.GetBytes("contenido adjunto");
var upload = await dinaupClient.File_UploadBytesAsync(
dinaupClient.DefaultSession,
bytes,
"nota.txt"
);
await dinaupClient.Annotation_PutAsync(
dinaupClient.DefaultSession,
sectionId,
rowId.ToString(),
upload.FileId, // adjuntamos el archivo
"Comentario con adjunto",
AnnotationTypeE.Comments
);
var resultado = await dinaupClient.Annotations_GetAsync(
dinaupClient.DefaultSession,
sectionId,
rowId,
AnnotationTypeE.Comments
);
foreach (var anotacion in resultado.Annotations)
{
var texto = anotacion.Text;
var adjuntos = anotacion.AttachedFiles; // si hay archivos adjuntos
}
var documentoSesionExecutor = new DynamicDocuments.APID.SesionC();
// Pasa la sesión actual.
// Si dispones de una sesión de usuario distinta, úsala; en caso contrario, usa la sesión por defecto.
await documentoSesionExecutor.ExecuteAsync(dinaupClient, dinaupClient.DefaultSession);
Guid paisId = /* Id del país */;
var pais = await MyDinaup.SectionsD.PaisesD.GetRowByIdAsync(dinaupClient, paisId);
// Usa pais.Propiedad...
var filtros = new List<FilterCondition>
{
new FilterCondition(
MyDinaup.SectionsD.PaisesD.PaisesES.CodigoDePaisAlfabeticoDe2Caracteres,
"=",
"ES"
)
};
var parametros = new RowsRequestParameters(filtros.ToArray());
var paises = await MyDinaup.SectionsD.PaisesD.GetRowsAsync(
dinaupClient,
parametros,
dinaupClient.DefaultSession
);
// Iterar resultados
foreach (var p in paises.Rows)
{
// p.Propiedad...
}
Guid sectionId = /* sección destino */;
var data = new Dictionary<string, string>
{
{
SeccionDePruebasAPIES.TextoPrincipal,
$"Prueba {Guid.NewGuid()}"
}
};
var wOp = new WriteOperation("", data); // "" => alta
var result= dinaupClient.RunWriteOperation(
dinaupClient.DefaultSession,
SeccionDePruebasAPIES.SectionId,
wOp,
false
);
// Lanza excepción si hubo errores globales
result.EnsureSuccess();
Guid newId = wOp.WriteOperationResult.RowID;
Guid rowId = /* Id del registro a editar */;
var data = new Dictionary<string, string>
{
{
SeccionDePruebasAPIES.TextoPrincipal,
$"Prueba {Guid.NewGuid()}"
}
};
var wOp= new WriteOperation(rowId, data);
var result= dinaupClient.RunWriteOperation(
dinaupClient.DefaultSession,
sectionId,
wOp,
false
);
// Lanza excepción si hubo errores globales
result.EnsureSuccess();
Guid updatedId = wOp.WriteOperationResult.RowID;
var operaciones = new List<WriteOperation>();
for (int i = 0; i < 10; i++)
{
var fila = new Dictionary<string, string>
{
{
SeccionDePruebasAPID.SeccionDePruebasAPIES.TextoPrincipal,
$"Lote {i}: {Guid.NewGuid()}"
}
};
operaciones.Add(new WriteOperation("", fila)); // alta
}
var batchAdd = dinaupClient.RunWriteOperation(
dinaupClient.DefaultSession,
sectionId,
operaciones,
false
);
var ids = operaciones.Select(o => o.WriteOperationResult.RowID).ToList();
// Partiendo de la lista 'ids' creada en el ejemplo anterior
var operacionesEdicion = new List<WriteOperation>();
foreach (var id in ids)
{
var actualizado = new Dictionary<string, string>
{
{
SeccionDePruebasAPID.SeccionDePruebasAPIES.TextoPrincipal,
$"Editado {DateTime.UtcNow.Ticks}"
}
};
operacionesEdicion.Add(new WriteOperation(id.ToString(), actualizado)); // edición
}
var batchEdit = dinaupClient.RunWriteOperation(
dinaupClient.DefaultSession,
sectionId,
operacionesEdicion,
false
);