
In diesem Tutorial zeige ich dir, wie du die Entwicklungszeit von Tagen auf Stunden reduzierst und einen eigenen REST-Endpoint für eine Adressvalidierung erstellst.
Das Ziel: Adressvalidierung in Echtzeit
Wir bauen einen API-Endpoint, der eine Adresse entgegennimmt, sie gegen einen externen Dienst prüft (z. B. eine kostenlose API wie OpenStreetMap oder Geoapify) und das Ergebnis zurückgibt. Das verhindert fehlerhafte Stammdaten direkt an der Quelle.
Schritt 1: Die Vorbereitung
Bevor wir starten, navigiere in deiner Matrix42 UUX Administration zu: Administration → Integration → Web Services.
Du kannst einen bestehenden Web Service erweitern oder einen neuen Container-Web-Service erstellen. Für dieses Beispiel nutzen wir den existierenden Service “userinfo”.
Schritt 2: Operation anlegen
Suche den Web Service, den du erweitern möchtest, klicke ihn an und wähle in der Vorschau die Aktion "Add Operation" .
Fülle das Formular wie folgt aus:
Name: ValidateAddress – Ein lesbarer Name für die Operation.
Method: GET – Da wir Daten abrufen wollen.
Route Template: validate/address – Dies definiert den URL-Pfad. Der finale Aufruf wird später so aussehen: https://<server>/m42services/api/<service>/validate/address.
Return Type: Object – Da wir ein JSON-Objekt zurückgeben wollen (oder String, wenn du nur Text brauchst).

Schritt 3: Das PowerShell-Skript (The Magic)
Das Herzstück ist das Skript-Feld. Hier definieren wir Input, Logik und Output. Wir nutzen Standard-PowerShell und spezifische Matrix42-Bindings.
Kopiere diesen Code in das Script-Fenster:
-------------------------------------------------------------------------------------------
# 1. Parameter definieren
param(
[QueryString][string]$street,
[QueryString][string]$city,
[QueryString][string]$zip
)
# Hilfsfunktion für sicheres Logging (falls Variablen null sind)
function Get-SafeStr($val) { if ($val) { return $val } else { return "NULL" } }
$M42_Log.Info("Input erhalten - Strasse: {0}, PLZ: {1}, Stadt: {2}", (Get-SafeStr $street), (Get-SafeStr $zip), (Get-SafeStr $city))
# 2. Validierung: Abbrechen, wenn keine sinnvollen Daten da sind
if ([string]::IsNullOrWhiteSpace($street) -and [string]::IsNullOrWhiteSpace($city)) {
return @{
Success = $false
Message = "Abbruch: Keine Strasse oder Stadt übergeben."
}
}
try {
# 3. URL und Encoding (Sicherer Aufbau)
$baseUrl = "https://nominatim.openstreetmap.org/search"
# Sicherstellen, dass wir keine Null-Werte encoden (das würde crashen)
$s_enc = if ($street) { [Uri]::EscapeDataString($street.Trim()) } else { "" }
$c_enc = if ($city) { [Uri]::EscapeDataString($city.Trim()) } else { "" }
$z_enc = if ($zip) { [Uri]::EscapeDataString($zip.Trim()) } else { "" }
# URL manuell zusammensetzen
$finalUri = "$($baseUrl)?street=$($s_enc)&city=$($c_enc)&postalcode=$($z_enc)&format=json&addressdetails=1&limit=1"
# DEBUG: Wir loggen die generierte URL (ohne API Key, da hier keiner nötig ist), um den Fehler zu sehen
$M42_Log.Info("Generierte URI: {0}", $finalUri)
# Header
$headers = @{
"User-Agent" = "Matrix42-Scripted-Op/1.0"
}
# 4. Request abfeuern
# ErrorAction Stop erzwingt, dass Fehler im 'catch' Block landen
$response = Invoke-RestMethod -Uri $finalUri -Headers $headers -Method Get -ErrorAction Stop
if ($response -and $response.Count -gt 0) {
$bestMatch = $response[0]
return @{
Success = $true
ValidAddress = $bestMatch.display_name
Lat = $bestMatch.lat
Lon = $bestMatch.lon
}
} else {
return @{
Success = $false
Message = "Keine Ergebnisse gefunden."
}
}
}
catch {
# 5. Detailliertes Error Handling
$errTitle = $_.Exception.Message
$errInner = if ($_.Exception.InnerException) { $_.Exception.InnerException.Message } else { "" }
$M42_Log.Error("CRITICAL API ERROR: {0} | Detail: {1}", $errTitle, $errInner)
return @{
Success = $false
Error = $errTitle
Detail = $errInner
}
}
Was passiert hier im Code?
Parameter Binding: Durch [QueryString] weiß Matrix42, dass es Variablen wie ?street=Hauptstr aus der URL direkt in die PowerShell-Variable $street mappen soll.
Logging: $M42_Log ist dein bester Freund für Debugging. Nutze es, um den Flow nachzuvollziehen. Die daten werden in die CommonLog geschrieben.
Invoke-RestMethod: Da Scripted Web Operations auf Standard-PowerShell basieren, kannst du externe REST-APIs einfach konsumieren – genau wie in der Konsole.
Schritt 4: Speichern und Testen
Klicke auf Fertigstellen. Der Endpoint ist sofort aktiv – kein Kompilieren, kein Server-Neustart, kein Deployment-Zyklus.

So testest du es: Öffne deinen Browser oder ein Tool wie Postman und rufe die URL auf (du musst authentifiziert sein):
https://dein-server.com/m42services/api/validate/address?street=hohenrainstrasse 24&zip=4133&city=Pratteln
Du erhältst sofort ein JSON-Ergebnis zurück, das du in UUX-Formularen oder Workflows weiterverarbeiten kannst.

Best Practices für den produktiven Einsatz
Damit dein Skript nicht nur läuft, sondern auch sicher ist, beachte diese Tipps aus der Praxis:
Security First
Keine Hardcoded Credentials: Speichere niemals Passwörter oder API-Keys im Skripttext. Nutze stattdessen das Service Connection Feature von Matrix42. Du kannst im Skript via $M42_ServiceConnection und $M42_DatabaseProvider auf sicher hinterlegte Anmeldedaten zugreifen (z. B. für Entra ID oder SQL)
Input Validation ist Pflicht: Vertraue keinen Eingaben. Wenn ein Parameter [QueryString]$id erwartet, prüfe im Skript, ob es wirklich eine GUID ist oder ob schädlicher Code enthalten sein könnte. Scripted Operations sind Einfallstore – validiere jeden Input, bevor du ihn verarbeitest
Audience Restriction (Zugriffssteuerung): Standardmässig dürfen oft nur Administratoren neue Operations aufrufen. Nutze die Aktion "Set Audience" (Zielgruppe festlegen) in der Administrationsoberfläche, um explizit zu definieren, welche Rollen oder Benutzer diesen Endpunkt konsumieren dürfen. Öffne die API nicht weiter als nötig.
Code-Qualität & Entwicklung
Schreibe deine Skripte so, dass sie auch in zwei Jahren noch wartbar sind.
Lokale Entwicklung: Der Editor im Browser ist für komplexen Code ungeeignet. Entwickle und teste deine Logik lokal in VS Code oder der PowerShell ISE. Nutze dort Features wie IntelliSense und Syntax-Highlighting. Kopiere den Code erst in Matrix42, wenn die Logik steht.
Parameter Binding nutzen: Parsen den Input nicht manuell. Nutze die Matrix42-Attribute, um Daten sauber zu empfangen:
◦ [QueryString] für einfache Filter (z.B. ?status=active).
◦ [Body] für komplexe JSON-Objekte bei POST/PUT-Requests.
◦ [Path] für saubere URLs (z.B. /api/ticket/{id}).
Logging: Nutze $M42_Log, um den Ablauf nachzuvollziehen. Logge Start, Ende und kritische Fehler. Das hilft enorm beim Debugging, da du nicht interaktiv in den Prozess eingreifen kannst.
◦ Tipp: Logge keine sensiblen Daten (wie Passwörter) im Klartext!
Fehlerbehandlung (Try/Catch): Externe APIs sind nicht immer erreichbar. Umschliesse deine Invoke-RestMethod Aufrufe zwingend mit try { ... } catch { ... }. Gib im Fehlerfall eine saubere JSON-Antwort an den Client zurück, statt das Skript abstürzen zu lassen (HTTP 500).
Lifecycle & Testing
Postman/Bruno nutzen: Teste deine API-Endpunkte ausgiebig mit Tools wie Postman, bevor du sie in UUX-Formularen verbaust. Prüfe auch "Edge Cases" (Was passiert, wenn die ID nicht existiert? Was bei Sonderzeichen?).
Versionierung: Da der Code direkt in der Datenbank liegt, ist Versionierung schwierig.
◦ Profi-Tipp: Pflege den Code parallel in einem Git-Repository.
◦ Dokumentiere Änderungen direkt im Feld "Dokumentation" der Operation.
Deployment: Nutze Extension Packages, um deine Scripted Operations von der Entwicklungs- in die Produktionsumgebung zu transportieren, statt Code manuell zu kopieren
Fazit
Mit Scripted Web Operations hast du den "Kran" für deine Daten-Container drastisch vereinfacht. Statt tagelanger C#-Entwicklung kannst du Integrationen in wenigen Stunden umsetzen – wartbar direkt durch Administratoren.

