Blog

Dein erster API-Endpoint in 30 MinutenScripted Web Operations in Matrix42

Pratteln, 17.09.2025
Stell dir Matrix42 wie ein riesiges Containerschiff vor. Die Container sind deine API-Endpunkte: standardisiert, aber flexibel befüllbar. Früher musstest du für jeden neuen Container einen speziellen Kran bauen (C# Web Service Entwicklung), was Tage dauerte. Heute nutzen wir Scripted Web Operations – das ist der schnelle Kran, gesteuert durch einfaches PowerShell.
 

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.

Hängst du an einer Stelle fest? Ich helfe
dir gerne persönlich weiter.

Dominik Vogt
T +41 77 434 48 54
dominik.vogt@xamplo.com