.NET Client
Der ProcessCube® .NET Client ist eine vollständige C# Library für die Integration mit der ProcessCube® Engine. Sie unterstützt .NET Core, .NET Framework und bietet eine moderne, asynchrone API mit vollem Async/Await-Support.
Überblick
Der .NET Client ermöglicht die nahtlose Integration von ProcessCube® Prozessen in .NET-Anwendungen. Mit vollständiger C#-Typisierung, LINQ-Support und modernem async/await ist er ideal für Enterprise-Anwendungen, Microservices und Windows-Services.
Hauptfeatures
- Vollständige C#-Typisierung: IntelliSense und Compile-Time Type-Safety
- Async/Await: Moderne asynchrone API mit Task-basiertem Muster
- .NET Core & Framework: Läuft auf beiden Plattformen
- OAuth 2.0 Support: Integration mit ProcessCube® Authority
- External Task Workers: Mit Hosting-Integration für ASP.NET Core
- Dependency Injection: Vollständige DI-Unterstützung
- Serialization: Anpassbare JSON-Serialisierung
Installation
NuGet Package Manager
dotnet add package ProcessCube.ClientPackage Manager Console
Install-Package ProcessCube.Client.csproj File
<ItemGroup>
<PackageReference Include="ProcessCube.Client" Version="1.0.0" />
</ItemGroup>Der .NET Client benötigt .NET Core 6.0+ oder .NET Framework 4.7.2+.
Quick Start
Client erstellen
Der einfachste Weg, einen Client zu erstellen:
using ProcessCube.Client;
// Client ohne Authentifizierung (nur für lokale Entwicklung)
var client = new ProcessCubeClient("http://localhost:8000");Mit Authentifizierung
Für produktive Umgebungen mit ProcessCube® Authority:
using ProcessCube.Client;
using ProcessCube.Client.Authentication;
var credentials = new ClientCredentials
{
ClientId = "your-client-id",
ClientSecret = "your-client-secret",
AuthorityUrl = "http://localhost:11235"
};
var client = new ProcessCubeClient("http://localhost:8000", credentials);Prozess starten
Ein einfaches Beispiel zum Starten eines Prozesses:
// Prozess ohne Parameter starten
var result = await client.StartProcessAsync("MyProcessKey");
Console.WriteLine($"Process started: {result.ProcessInstanceId}");Mit Parametern starten
// Prozess mit Eingabeparametern starten
var inputValues = new Dictionary<string, object>
{
["customerName"] = "Max Mustermann",
["orderAmount"] = 1500
};
var result = await client.StartProcessAsync("OrderProcess", inputValues);
Console.WriteLine($"Process Instance ID: {result.ProcessInstanceId}");
Console.WriteLine($"Result: {result.Result}");Wichtige Konzepte
Prozess-Management
Application Info abrufen
// Engine-Informationen abrufen
var info = await client.GetApplicationInfoAsync();
Console.WriteLine($"Engine Version: {info.Version}");
Console.WriteLine($"Engine URL: {info.Url}");Prozesse abfragen
// Alle deployten Prozesse abrufen
var processes = await client.GetProcessesAsync();
foreach (var process in processes)
{
Console.WriteLine($"{process.Key}: {process.Name}");
}Prozess-Instanzen abfragen
using ProcessCube.Client.Models;
// Laufende Prozess-Instanzen abrufen
var query = new ProcessInstanceQuery
{
ProcessKey = "OrderProcess",
State = ProcessInstanceState.Running
};
var instances = await client.GetProcessInstancesAsync(query);
foreach (var instance in instances)
{
Console.WriteLine($"Instance: {instance.ProcessInstanceId}");
Console.WriteLine($"State: {instance.State}");
}User Task Handling
User Tasks abrufen
// Alle offenen User Tasks abrufen
var userTasks = await client.GetUserTasksAsync();
// Nach Prozess-Instanz filtern
var tasksForInstance = await client.GetUserTasksAsync(new UserTaskQuery
{
ProcessInstanceId = "instance-123"
});
foreach (var task in userTasks)
{
Console.WriteLine($"Task: {task.Id}");
Console.WriteLine($"Name: {task.Name}");
}User Task abschließen
// User Task mit Ergebnis abschließen
var resultData = new Dictionary<string, object>
{
["approved"] = true,
["comment"] = "Genehmigt durch Manager"
};
await client.FinishUserTaskAsync(task.Id, resultData);External Task Pattern
Manuelles External Task Handling
// External Tasks abrufen und verarbeiten
var externalTasks = await client.FetchAndLockExternalTasksAsync(
topicName: "SendEmail",
workerId: "worker-1",
maxTasks: 5
);
foreach (var task in externalTasks)
{
try
{
// Task-Parameter auslesen
var recipient = task.Variables["recipient"].ToString();
var subject = task.Variables["subject"].ToString();
var body = task.Variables["body"].ToString();
// E-Mail versenden (Pseudo-Code)
await SendEmailAsync(recipient, subject, body);
// Task als erfolgreich abgeschlossen markieren
var result = new Dictionary<string, object>
{
["success"] = true,
["sentAt"] = DateTime.UtcNow
};
await client.CompleteExternalTaskAsync(task.Id, "worker-1", result);
}
catch (Exception ex)
{
// Task als fehlgeschlagen markieren
await client.HandleExternalTaskBpmnErrorAsync(
task.Id,
"worker-1",
"EMAIL_SEND_ERROR",
ex.Message
);
}
}External Task Workers mit Hosting
Für ASP.NET Core-Anwendungen:
using ProcessCube.Client.ExternalTasks;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs oder Program.cs
services.AddProcessCubeClient(options =>
{
options.EngineUrl = "http://localhost:8000";
options.ClientId = "my-service";
options.ClientSecret = "secret-key";
options.AuthorityUrl = "http://localhost:11235";
});
services.AddExternalTaskWorker<EmailWorker>("SendEmail");
// Worker-Klasse
public class EmailWorker : IExternalTaskWorker
{
private readonly IEmailService _emailService;
public EmailWorker(IEmailService emailService)
{
_emailService = emailService;
}
public async Task<IDictionary<string, object>> ExecuteAsync(
ExternalTask task,
CancellationToken cancellationToken)
{
var recipient = task.Variables["recipient"].ToString();
var subject = task.Variables["subject"].ToString();
var body = task.Variables["body"].ToString();
await _emailService.SendAsync(recipient, subject, body);
return new Dictionary<string, object>
{
["success"] = true,
["sentAt"] = DateTime.UtcNow
};
}
}External Task Workers mit Hosting-Integration laufen als Background-Service und pollen die Engine automatisch.
Event Handling
Signal senden
// Signal an laufende Prozesse senden
await client.SendSignalAsync(
"PaymentReceived",
new Dictionary<string, object>
{
["orderId"] = "ORDER-123",
["amount"] = 1500
}
);Message senden
// Message an spezifische Prozess-Instanz senden
await client.SendMessageAsync(
"UpdateOrder",
new Dictionary<string, object>
{
["status"] = "shipped",
["trackingNumber"] = "TRACK-456"
},
processInstanceId: "instance-123"
);Authentifizierung
Client Credentials Flow
Für Service-to-Service Kommunikation:
var credentials = new ClientCredentials
{
ClientId = "my-service",
ClientSecret = "secret-key",
AuthorityUrl = "http://localhost:11235"
};
var client = new ProcessCubeClient("http://localhost:8000", credentials);
// Client authentifiziert sich automatisch beim ersten Request
var processes = await client.GetProcessesAsync();Mit User Token
Für Benutzer-Anwendungen:
var authOptions = new AuthorizationCodeOptions
{
ClientId = "my-app",
AuthorityUrl = "http://localhost:11235",
RedirectUri = "http://localhost:5000/callback",
Scopes = new[] { "openid", "profile", "engine_read", "engine_write" }
};
var client = new ProcessCubeClient("http://localhost:8000", authOptions);
// Login-Flow initiieren
await client.LoginAsync();Dependency Injection
ASP.NET Core Integration
using ProcessCube.Client;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs oder Program.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddProcessCubeClient(options =>
{
options.EngineUrl = Configuration["ProcessCube:EngineUrl"];
options.ClientId = Configuration["ProcessCube:ClientId"];
options.ClientSecret = Configuration["ProcessCube:ClientSecret"];
options.AuthorityUrl = Configuration["ProcessCube:AuthorityUrl"];
});
services.AddControllers();
}
// In einem Controller
[ApiController]
[Route("api/[controller]")]
public class ProcessController : ControllerBase
{
private readonly IProcessCubeClient _client;
public ProcessController(IProcessCubeClient client)
{
_client = client;
}
[HttpPost("start")]
public async Task<IActionResult> StartProcess([FromBody] OrderData orderData)
{
try
{
var result = await _client.StartProcessAsync("OrderProcess", orderData);
return Ok(new
{
Success = true,
ProcessInstanceId = result.ProcessInstanceId
});
}
catch (Exception ex)
{
return StatusCode(500, new { Error = ex.Message });
}
}
}Custom Serialization
Anpassen der JSON-Serialisierung
using System.Text.Json;
using System.Text.Json.Serialization;
var serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Converters = { new JsonStringEnumConverter() }
};
var client = new ProcessCubeClient(
"http://localhost:8000",
serializerOptions: serializerOptions
);Custom HTTP Client
var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
var client = new ProcessCubeClient(
"http://localhost:8000",
httpClient: httpClient
);Best Practices
Error Handling
using ProcessCube.Client.Exceptions;
try
{
await client.StartProcessAsync("NonExistentProcess");
}
catch (ProcessNotFoundException ex)
{
Console.WriteLine($"Process does not exist: {ex.ProcessKey}");
}
catch (ProcessCubeException ex)
{
Console.WriteLine($"Engine error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unknown error: {ex}");
}Using Pattern
using (var client = new ProcessCubeClient("http://localhost:8000"))
{
var result = await client.StartProcessAsync("MyProcess");
Console.WriteLine($"Process started: {result.ProcessInstanceId}");
}
// Client wird automatisch disposedConfiguration
// appsettings.json
{
"ProcessCube": {
"EngineUrl": "http://localhost:8000",
"ClientId": "my-service",
"ClientSecret": "secret-key",
"AuthorityUrl": "http://localhost:11235"
}
}// In Program.cs oder Startup.cs
services.AddProcessCubeClient(options =>
{
Configuration.GetSection("ProcessCube").Bind(options);
});Framework-Integrationen
Windows Service
using Microsoft.Extensions.Hosting;
public class ProcessWorkerService : BackgroundService
{
private readonly IProcessCubeClient _client;
private readonly ILogger<ProcessWorkerService> _logger;
public ProcessWorkerService(
IProcessCubeClient client,
ILogger<ProcessWorkerService> logger)
{
_client = client;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
// External Tasks abrufen und verarbeiten
var tasks = await _client.FetchAndLockExternalTasksAsync(
"ProcessOrders",
"worker-1",
5
);
foreach (var task in tasks)
{
await ProcessTaskAsync(task);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing tasks");
}
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
}
}Blazor WebAssembly
// In Program.cs
builder.Services.AddScoped<IProcessCubeClient>(sp =>
new ProcessCubeClient("http://localhost:8000")
);
// In einer Blazor-Komponente
@inject IProcessCubeClient ProcessClient
@code {
private List<ProcessModel> processes = new();
protected override async Task OnInitializedAsync()
{
processes = await ProcessClient.GetProcessesAsync();
}
}Console Application
using ProcessCube.Client;
class Program
{
static async Task Main(string[] args)
{
var client = new ProcessCubeClient("http://localhost:8000");
var result = await client.StartProcessAsync("MyProcess", new
{
input = "Hello World"
});
Console.WriteLine($"Started: {result.ProcessInstanceId}");
}
}Troubleshooting
Connection Issues
Problem: Client kann keine Verbindung zur Engine herstellen
Lösungen:
- Prüfen Sie die Engine-URL in appsettings.json
- Stellen Sie sicher, dass die Engine läuft
- Überprüfen Sie Firewall-Einstellungen
- Testen Sie mit:
curl http://localhost:8000/api/info
Authentication Errors
Problem: 401 Unauthorized Fehler
Lösungen:
- Prüfen Sie ClientId und ClientSecret
- Stellen Sie sicher, dass der Client in der Authority registriert ist
- Überprüfen Sie die AuthorityUrl
- Prüfen Sie erforderliche Scopes in der Authority-Konfiguration
Serialization Issues
Problem: JSON-Serialisierungsfehler
Lösungen:
- Verwenden Sie System.Text.Json (empfohlen) oder Newtonsoft.Json
- Konfigurieren Sie JsonSerializerOptions korrekt
- Prüfen Sie Property-Naming (camelCase vs PascalCase)
Weitere Ressourcen
- GitHub Repository - Quellcode und Beispiele
- NuGet Package - Paket-Informationen
- API Reference - Vollständige API-Dokumentation (folgt in Phase 2)
- ProcessCube® Engine - Engine-Dokumentation
- ProcessCube® Authority - Authority-Dokumentation
Support
Bei Fragen oder Problemen:
- GitHub Issues: Probleme melden
- Discussions: Community-Support auf GitHub Discussions