C# (.NET)
Un programa de consola en C# que usa la API con HttpClient y System.Net.Http.Json, ambos incluidos en .NET: no hay que instalar paquetes. Enumera las variables etiquetadas de una plantilla, mide el dibujo que genera con los valores dados y lo exporta como PDF.
Descárguelo: Program.cs, o el proyecto completo, el programa con su archivo de proyecto, como piq-saas-csharp.zip.
// Program.cs: list a template's inputs, measure it and export it as a PDF with the PiQ SaaS API.
// .NET 8 or later; HttpClient and System.Net.Http.Json, no packages needed.
using System.Net.Http.Json;
using System.Text.Json;
var key = Environment.GetEnvironmentVariable("PIQ_API_KEY");
var baseUrl = Environment.GetEnvironmentVariable("PIQ_URL") ?? "https://saas.parametriq.co.uk";
var storage = Environment.GetEnvironmentVariable("PIQ_STORAGE"); // optional: a registered storage's name
if (string.IsNullOrEmpty(key))
{
Console.Error.WriteLine("Set PIQ_API_KEY to your API key.");
return 1;
}
const string Template =
"L=400,\"Length\"\nW=300,\"Width\"\nP1=[L,0]\nP2=[L,W]\nP3=[0,W]\nPOLYLINE @1,[P0,P1,P2,P3],TRUE,0";
// the template itself, or (optional) where it is kept in your storage
object? source = storage is null ? null : new { storage, key = "templates/box.piq" };
string? template = storage is null ? Template : null;
var values = new Dictionary<string, object> { ["L"] = 500, ["W"] = 250 };
using var http = new HttpClient { BaseAddress = new Uri(baseUrl.TrimEnd('/') + "/") };
http.DefaultRequestHeaders.Add("X-API-KEY", key);
var json = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull };
async Task<HttpResponseMessage> Post(string path, object body)
{
var response = await http.PostAsJsonAsync(path, body, json);
if (response.IsSuccessStatusCode) return response;
Console.Error.WriteLine($"Error {(int)response.StatusCode} {response.ReasonPhrase}");
var text = await response.Content.ReadAsStringAsync(); // a 401 has no body
if (text.Length > 0)
{
try
{
var problem = JsonSerializer.Deserialize<Problem>(text, json)!;
if (problem.Title is not null) Console.Error.WriteLine(problem.Title);
if (problem.Detail is not null) Console.Error.WriteLine(problem.Detail);
foreach (var (field, messages) in problem.Errors ?? [])
Console.Error.WriteLine($" {field}: {string.Join(" ", messages)}");
}
catch (JsonException) { Console.Error.WriteLine(text); }
}
Environment.Exit(1);
return response;
}
async Task<T> PostFor<T>(string path, object body) =>
(await (await Post(path, body)).Content.ReadFromJsonAsync<T>(json))!;
// 1. The template's labelled variables
var inputs = await PostFor<InputsResponse>("inputs", new { template, source });
foreach (var i in inputs.Inputs)
Console.WriteLine($"{i.Name}: {i.Label} ({i.Kind}, {i.Value})");
// 2. The drawing measured, with the values given
var m = await PostFor<MeasureResponse>("measure", new { template, source, values });
var cut = m.Layers.FirstOrDefault(l => l.Layer == "Cut")?.Length ?? 0;
Console.WriteLine($"Size: {m.Width} x {m.Height}, cut length: {cut}");
// 3. The drawing as a PDF
var pdf = await Post("export/pdf", new { template, source, values });
await File.WriteAllBytesAsync("box.pdf", await pdf.Content.ReadAsByteArrayAsync());
Console.WriteLine($"Saved box.pdf ({pdf.Headers.GetValues("X-PiQ-Warnings").First()} warnings)");
// 4. Optional: the PDF saved to your storage instead of downloaded
if (storage is not null)
{
var destination = new { storage, key = "drawings/box.pdf" };
var body = new { source, values, destination, overwrite = true };
var saved = await PostFor<SavedFileResponse>("save/pdf", body);
Console.WriteLine($"Saved {saved.Key} to {saved.Storage} ({saved.Size} bytes)");
}
return 0;
record InputResponse(string Name, string Label, string Kind, JsonElement Value);
record InputsResponse(List<InputResponse> Inputs);
record LayerLengthResponse(string Layer, double Length);
record MeasureResponse(double Width, double Height, List<LayerLengthResponse> Layers);
record SavedFileResponse(string Storage, string Key, long Size);
record Problem(string? Title, string? Detail, Dictionary<string, string[]>? Errors);
Cómo funciona
- Configuración. La clave se toma de
PIQ_API_KEY, la dirección dePIQ_URL(el propio servicio si no está definida) y, opcionalmente, el nombre de un almacenamiento dePIQ_STORAGE. Sin clave, el programa se detiene de inmediato. - La plantilla. Cada solicitud indica
template(el texto de la plantilla) o, cuandoPIQ_STORAGEestá definida,source(dónde está guardada en su almacenamiento); el otro esnull.valuesdaLyWpor nombre. - El cliente tiene la dirección del servicio como su
BaseAddressy la clave en el encabezadoX-API-KEYde cada solicitud. Las opciones del serializador son los valores predeterminados web de .NET (nombres en camelCase, como usa la API), omitiendo las propiedadesnull, de modo que solo se envía uno detemplateysource. Postenvía un cuerpo (un objeto anónimo) a una operación como JSON. Una respuesta correcta se devuelve para leerla. Cualquier otra respuesta se lee como texto: un401no tiene cuerpo, así que solo se analiza, comoProblem, cuando lo hay, y se imprimen sutitle, sudetaily cada entrada deerrors(el campo y qué está mal en él). Un cuerpo que no es JSON se imprime tal cual. Después, el programa termina con1.PostFor<T>envía la solicitud y lee la respuesta JSON comoT: los registros del final del programa solo tienen las propiedades que se usan aquí.- Inputs.
POST /inputssolo necesita la plantilla. Cada uno de susInputstiene un nombre, una etiqueta, un tipo y un valor; el valor es unJsonElement, ya que puede ser un número, un texto, otrueofalse. - Measure.
POST /measurecon los valores da el ancho y el alto del dibujo, y las longitudes de sus líneas por capa; la longitud de corte es la longitud en la capaCut. - Export.
POST /export/pdfresponde con el propio PDF, no con JSON: sus bytes se escriben enbox.pdf. El encabezadoX-PiQ-Warningsindica cuántas cosas no pudieron exportarse tal cual. - Save (opcional). Con un almacenamiento,
POST /save/pdfexporta el mismo dibujo y lo guarda en su almacenamiento endestination;overwrite = truereemplaza un archivo que ya exista. Responde con dónde lo ha guardado y su tamaño.
Cómo ejecutarlo
Descomprima piq-saas-csharp.zip (crea una carpeta Box, con el programa y su archivo de proyecto) y ejecútelo allí:
export PIQ_API_KEY=XXXX-XXXX-XXXX-XXXXX
dotnet run
O bien cree un proyecto de consola, ponga el programa en su Program.cs y ejecútelo:
dotnet new console -o Box
cd Box
# replace Program.cs with the program above
export PIQ_API_KEY=XXXX-XXXX-XXXX-XXXXX
dotnet run
En PowerShell, establezca la clave con $env:PIQ_API_KEY = "XXXX-XXXX-XXXX-XXXXX".
Con .NET 10, el programa también puede ejecutarse por sí solo, como dotnet run box.cs, sin proyecto. Un programa así
se compila de antemano, lo que deja fuera la reflexión que System.Text.Json usa aquí, así que su primera línea debe
ser #:property PublishAot=false.
Imprime las variables etiquetadas de la plantilla, el tamaño del dibujo y su longitud de corte, y guarda box.pdf:
L: Length (Number, 400)
W: Width (Number, 300)
D: Depth (Number, 300)
Size: 500 x 250, cut length: 1500
Saved box.pdf (0 warnings)
Con un valor que la plantilla no puede usar (por ejemplo, "L": "long"), imprime el problema y se detiene:
Error 400 Bad Request
One or more validation errors occurred.
Some of the values given can't be used.
L: L is a number.
Con una clave incorrecta, solo imprime Error 401 Unauthorized: un 401 no tiene
descripción del problema.
Para probar la parte del almacenamiento, registre un almacenamiento (consulte
Registrar un almacenamiento), coloque en él una plantilla como templates/box.piq y
establezca PIQ_STORAGE con el nombre del almacenamiento. La plantilla se lee entonces desde su almacenamiento, y el
PDF también se guarda en él como drawings/box.pdf, reemplazando cualquier archivo que ya exista.
Consulte también: API, Inputs, Measure, Exportar un dibujo, Guardar en su almacenamiento, Registrar un almacenamiento, Clientes.