Eingaben und Ergebnisse
Actions können ein Eingabemodell entgegennehmen und ein Ergebnis zurückgeben. Validierungsregeln werden am Eingabemodell definiert.
Eingabemodell definieren
Eine Action kann ein Eingabemodell entgegennehmen:
public sealed class LagerEinbuchenInput
{
public required string ArticleNumber { get; init; }
public required string Warehouse { get; init; }
public decimal Quantity { get; init; }
}
[Action("einbuchen", Display = "Lager einbuchen")]
public string LagerEinbuchen(LagerEinbuchenInput input)
{
var artikelLager = session.ArtikelLager(input.ArticleNumber);
artikelLager.Execute(new LagerEinbuchungBuilder(input.Warehouse, (double)input.Quantity)
.InLagerBuchen(true)
.Build());
return $"{input.Quantity} x {input.ArticleNumber} in Lager {input.Warehouse} gebucht.";
}
Das Eingabemodell bestimmt die Formularfelder und den JSON-Payload externer Aufrufe.
Eingaben validieren
Validierungsregeln werden mit .NET DataAnnotations direkt an den Properties definiert:
public sealed class LagerEinbuchenInput
{
[Required]
public required string ArticleNumber { get; init; }
[Required]
public required string Warehouse { get; init; }
[Range(0.0001, double.MaxValue)]
public decimal Quantity { get; init; }
}
Die Runtime validiert die Eingabe vor dem Methodenaufruf. Ungültige Werte führen zum Status Validierung fehlgeschlagen mit Angabe der betroffenen Felder.
Fachliche Prüfungen, etwa ob Artikel und Lager existieren, bleiben Teil der Buchungslogik.
Strukturierte Ergebnisse zurückgeben
Wenn eine Action mehrere Werte liefert, verwenden Sie dafür ein eigenes Ergebnismodell:
public sealed class LagerBuchungResult
{
public required string ArticleNumber { get; init; }
public required string Warehouse { get; init; }
public decimal Quantity { get; init; }
public DateTimeOffset BookedAt { get; init; }
public Guid RunId { get; init; }
}
Das Ergebnis erscheint in der Historie und wird bei HTTP-Aufrufen als JSON zurückgegeben.
AutomationContext stellt Metadaten zur laufenden Ausführung bereit:
public sealed class LagerModule(
IBpSession session,
AutomationContext context) : BpModule
{
public override string ModuleName => "Lagerbuchung";
public override string ModuleVersion => "1.0.0";
[Action("einbuchen", Display = "Lager einbuchen")]
public LagerBuchungResult LagerEinbuchen(LagerEinbuchenInput input)
{
session.ArtikelLager(input.ArticleNumber).Execute(
new LagerEinbuchungBuilder(input.Warehouse, (double)input.Quantity)
.InLagerBuchen(true)
.Build());
return new LagerBuchungResult
{
ArticleNumber = input.ArticleNumber,
Warehouse = input.Warehouse,
Quantity = input.Quantity,
BookedAt = DateTimeOffset.UtcNow,
RunId = context.RunId
};
}
}
Das Beispiel verändert Lagerbestände. Verwenden Sie zum Testen einen Testmandanten.
context.RunId ordnet das Ergebnis einer Ausführung zu.
Abbruch langer Ausführungen unterstützen
Prüfen Sie bei längeren Aktionen das CancellationToken zwischen den Arbeitsschritten:
[Action("export", Display = "Exportieren")]
public async Task<int> ExportAsync(ExportInput input, CancellationToken cancellationToken)
{
var anzahl = 0;
foreach (var adresse in LadeAdressen(input))
{
cancellationToken.ThrowIfCancellationRequested();
await SchreibeAsync(adresse, cancellationToken);
anzahl++;
}
return anzahl;
}
Das Token signalisiert einen Abbruch in Studio oder das Herunterfahren der Runtime. Bereits ausgeführte Änderungen werden durch einen Abbruch nicht zurückgenommen.
Eine Action akzeptiert optional ein Eingabemodell und ein CancellationToken. Ergebnisse
müssen serialisierbar sein; auch void, Task und Task<T> werden unterstützt.
Mehrere Actions organisieren
Vergeben Sie für jede Action eine eindeutige ID:
[Action("einbuchen", Display = "Lager einbuchen")]
public LagerBuchungResult LagerEinbuchen(LagerEinbuchenInput input) { ... }
[Action("umbuchen", Display = "Lager umbuchen")]
public LagerBuchungResult LagerUmbuchen(LagerUmbuchenInput input) { ... }
[Action("ausbuchen", Display = "Lager ausbuchen")]
public LagerBuchungResult LagerAusbuchen(LagerAusbuchenInput input) { ... }
Weitere Buchungsarten sind unter Lagerbuchungen im SDK beschrieben.