502 lines
19 KiB
Markdown
502 lines
19 KiB
Markdown
# Matrix42 26.1 Legacy Extension Migration
|
|
|
|
Diese Notizen dokumentieren die bisherigen Learnings aus der Migration einer alten Matrix42 Extension inklusive Custom Web Service auf eine Matrix42 26.1 Sandboxed Extension.
|
|
|
|
Die Anleitung ist bewusst als wiederverwendbare Checkliste fuer weitere Legacy-Pakete formuliert. Sie trennt zwischen belastbaren Ergebnissen, verworfenen Zwischenansaetzen und Punkten, die bei jeder Extension erneut geprueft werden muessen.
|
|
|
|
## Zielbild
|
|
|
|
- Extension als .NET 8 Library mit `Matrix42.WebApi.Contracts`.
|
|
- Webservice-Controller von `Matrix42.WebApi.Contracts.ApiController` ableiten.
|
|
- Controller ueber `Matrix42.Hosting.Contracts.IDependencyResolver` konstruieren.
|
|
- Matrix42-Fachservices nur dort lazy aufloesen, wo sie wirklich gebraucht werden.
|
|
- Host-Konfig mit minimalen Modulen starten und gezielt erweitern.
|
|
- Paketbau in MSBuild/Visual Studio integrieren.
|
|
- Paketversion aus `AssemblyVersion` ableiten.
|
|
- Signing nur fuer eine eigene signed Build-Konfiguration aktivieren.
|
|
- Postman-Collection als Regressionstest fuer alte Client-URLs pflegen.
|
|
|
|
## Ausgangspunkt
|
|
|
|
Bei einer Portierung eines alten Produktstands muss der Zielstand klar sein. Fuer diesen Branch war der relevante alte Stand `26eac54f94`, nicht der spaetere neue Codezweig.
|
|
|
|
Wichtiges Learning: Bei einem 26.1-Kompatibilitaetsport keine neuen fachlichen Methoden, Obsolete-Markierungen oder Verhaltensaenderungen aus einem anderen Codezweig uebernehmen. Erst die alte Funktionalitaet lauffaehig machen, dann separate fachliche Aenderungen behandeln.
|
|
|
|
## Basisprojekt
|
|
|
|
Bewaehrte Projekt-Eigenschaften:
|
|
|
|
```xml
|
|
<TargetFramework>net8.0</TargetFramework>
|
|
<OutputType>Library</OutputType>
|
|
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
|
|
<AppendRuntimeIdentifierToOutputPath>true</AppendRuntimeIdentifierToOutputPath>
|
|
<Nullable>disable</Nullable>
|
|
<ImplicitUsings>disable</ImplicitUsings>
|
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
|
<M42ExtensionId>...</M42ExtensionId>
|
|
<M42AssemblyPattern>...</M42AssemblyPattern>
|
|
<M42BuildPackage>true</M42BuildPackage>
|
|
```
|
|
|
|
Referenzen auf Matrix42-DLLs sollen gegen die 26.1 Libraries zeigen und normalerweise `Private=false` haben, damit keine unnoetigen Matrix42-Plattform-DLLs ins Paket kopiert werden.
|
|
|
|
Die Host-Konfig muss exakt zum Assembly-Namen passen:
|
|
|
|
```text
|
|
<AssemblyName>.dll.host.config
|
|
```
|
|
|
|
## Paketbau
|
|
|
|
Das Paket wird ueber `M42SandboxedExtension.targets` gebaut.
|
|
|
|
Aktuelle Regeln in diesem Repo:
|
|
|
|
- `Debug` baut Debug-DLLs und ein Debug-Paket.
|
|
- `Release` baut ein unsigniertes Release-Paket.
|
|
- `Release_signed` baut ein Release-Paket und aktiviert `M42SignAssemblies=true`.
|
|
- Artefakte liegen getrennt nach Konfiguration unter `artifacts/<Configuration>/`.
|
|
- Die Package-Version wird aus der `AssemblyVersion` der gebauten WebApi-Assembly gelesen.
|
|
- `M42PackageVersion` wurde entfernt und soll nicht wieder eingefuehrt werden.
|
|
|
|
Die zentrale Version liegt in `SharedAssemblyInfo.cs`.
|
|
|
|
Beispiele:
|
|
|
|
```powershell
|
|
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Debug
|
|
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release
|
|
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release_signed
|
|
```
|
|
|
|
Visual Studio:
|
|
|
|
- `Debug`: Debugging und Testpakete.
|
|
- `Release`: Release ohne Signierung.
|
|
- `Release_signed`: Release mit Signierung.
|
|
|
|
Signierbare MSBuild-Properties:
|
|
|
|
```powershell
|
|
/p:M42SignAssemblies=true
|
|
/p:M42SignTool="C:\Path\To\signtool.exe"
|
|
/p:M42SignCertificateThumbprint="<thumbprint>"
|
|
/p:M42SignCertificateFile="C:\Path\To\certificate.pfx"
|
|
/p:M42SignCertificatePassword="<password>"
|
|
/p:M42SignTimestampUrl="http://rfc3161timestamp.globalsign.com/advanced"
|
|
/p:M42SignOptions="/a"
|
|
```
|
|
|
|
## Package-Struktur
|
|
|
|
Das neue Paket basiert auf einem `PackageTemplate` mit:
|
|
|
|
- `package.json`
|
|
- `install.xml`
|
|
- `install/...`
|
|
- `BasePackage/Assemblies` als Build-Ziel fuer Assemblies
|
|
|
|
Beim Portieren eines Legacy-Pakets:
|
|
|
|
1. Altes Paket entpacken.
|
|
2. WebAPI-Service (`PLSLServiceTypeWebAPI`) und Operationen (`PLSLWebServiceOperation`) identifizieren.
|
|
3. Extension-/Assembly-ID beibehalten, wenn ein Update statt einer Neuinstallation gewollt ist.
|
|
4. Operation-IDs nur dann aendern, wenn bewusst neue Operationen entstehen sollen.
|
|
5. Obsolete oder entfernte Schema-Attribute aus 26.1 entfernen.
|
|
|
|
Konkretes 26.1-Learning:
|
|
|
|
- `UsedInTypeSPSActivityTypeAlert` gibt es in 26.1 nicht mehr und muss aus dem Paket entfernt werden.
|
|
|
|
## Host-Konfig und Module
|
|
|
|
Mit so wenig Modulen wie moeglich starten. Jedes zusaetzliche Modul kann transitive Unity-Registrierungen erzwingen, die bereits beim Controller- oder Service-Aufbau scheitern.
|
|
|
|
Minimaler Startpunkt fuer einfache Endpoints:
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="utf-8" ?>
|
|
<host xmlns="urn:m42/host.config">
|
|
<modules>
|
|
<module assembly="Matrix42.DataLayer.Persistence" />
|
|
</modules>
|
|
<sections></sections>
|
|
</host>
|
|
```
|
|
|
|
Der aktuelle Stand dieser Extension benoetigt fuer alle Funktionen mehr Module, insbesondere wegen Journal, Storage, Pandora, Teams Notification, ServiceConnection, Auth und Aurora Search. Aktuelle Host-Konfig:
|
|
|
|
```xml
|
|
<modules>
|
|
<module assembly="C4ITF4SDM42WebApi" />
|
|
<module assembly="Matrix42.DataLayer.Persistence" />
|
|
<module assembly="Matrix42.Services.WebApi" />
|
|
<module assembly="Matrix42.ServiceRepository.BizLogic" />
|
|
<module assembly="Matrix42.Pandora.ServiceStore" />
|
|
<module assembly="Matrix42.Pandora.Persistence" />
|
|
<module assembly="Matrix42.Pandora.BizLogic" />
|
|
<module assembly="Matrix42.Pandora.Services" />
|
|
<module assembly="Matrix42.Distributed.Redis.Cache" />
|
|
<module assembly="Matrix42.StorageService.BizLogic" />
|
|
<module assembly="Matrix42.MsTeamsNotification.BizLogic" />
|
|
<module assembly="Matrix42.ServiceConnection.Persistence" />
|
|
<module assembly="Matrix42.Auth.BizLogic" />
|
|
<module assembly="Matrix42.ServiceConnection.BizLogic" />
|
|
<module assembly="Matrix42.Integration.Aurora.General" />
|
|
<module assembly="Matrix42.Integration.Aurora.Search.BizLogic" />
|
|
<module assembly="update4u.SPS.ComplianceRules.BizLogic" />
|
|
<module assembly="update4u.SPS.Security" />
|
|
<module assembly="Matrix42.BizLogic.Journal" />
|
|
<module assembly="Matrix42.ServiceManager.BizLogic" />
|
|
</modules>
|
|
```
|
|
|
|
Regel: Wenn ein weiteres Interface nicht aufgeloest werden kann, nicht raten. In den Matrix42-DLLs nach dem Registrator/der Implementierung fuer genau dieses Interface suchen und nur das passende Modul laden.
|
|
|
|
## Controller-Konstruktion
|
|
|
|
Nicht so:
|
|
|
|
```csharp
|
|
public MyController(IEntityDataService entityDataService, IJournalService journalService, IPandoraUserProfile userProfile)
|
|
```
|
|
|
|
Das zwingt Unity, alle Services schon beim Erzeugen des Controllers aufzuloesen. Dadurch kann bereits `isAlive` scheitern, obwohl der Endpoint selbst keinen dieser Services braucht.
|
|
|
|
Bewaehrt:
|
|
|
|
```csharp
|
|
private readonly IDependencyResolver _resolver;
|
|
|
|
public MyController(IDependencyResolver resolver, IEnumerationProvider enumerationProvider)
|
|
{
|
|
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
|
|
_enumerationProvider = enumerationProvider ?? throw new ArgumentNullException(nameof(enumerationProvider));
|
|
}
|
|
|
|
private T GetRequiredService<T>() where T : class
|
|
{
|
|
var service = _resolver.TryGet<T>();
|
|
if (service != null)
|
|
return service;
|
|
|
|
throw new InvalidOperationException($"Required Matrix42 service is not registered: {typeof(T).FullName}");
|
|
}
|
|
```
|
|
|
|
Fachservices im jeweiligen Endpoint oder Helper lazy aufloesen.
|
|
|
|
## Dependency-Registrator
|
|
|
|
Die Extension kann eigene Sandbox-Registrierungen bereitstellen, wenn der Matrix42-Sandbox-Host eine Plattform-Instanz nicht selbst registriert.
|
|
|
|
Konkretes Learning:
|
|
|
|
- Fuer den Journal-Pfad fehlte `System.Web.Http.Description.IApiExplorer`.
|
|
- Die Extension registriert eine konkrete `ApiExplorer`-Instanz ueber `IDependencyRegistrator`.
|
|
- Das eigene Assembly muss dafuer als Host-Modul geladen werden.
|
|
|
|
Das ist kein Workaround im fachlichen Code, sondern eine Host-Registrierung fuer eine fehlende Infrastruktur-Dependency.
|
|
|
|
## WebAPI-Rueckgaben
|
|
|
|
Matrix42 serialisiert `HttpResponseMessage` in dieser Runtime nicht wie klassische ASP.NET Web API, sondern als Nutzdatenobjekt.
|
|
|
|
Nicht fuer normale Datenendpoints verwenden:
|
|
|
|
```csharp
|
|
Task<HttpResponseMessage>
|
|
HttpResponseExtensions.CreateResponse(...)
|
|
```
|
|
|
|
Symptom:
|
|
|
|
```json
|
|
{"Version":"1.1","Content":{...},"StatusCode":200}
|
|
```
|
|
|
|
Bewaehrt:
|
|
|
|
- Datenendpoints geben direkte Nutzdaten zurueck, z. B. `Task<List<T>>`, `Task<object>` oder `Task<EntityEnumeration>`.
|
|
- Leere Listen duerfen nicht `null` sein.
|
|
- `isAlive` gibt `IHttpActionResult` mit `StatusCodeResult(HttpStatusCode.NoContent)` zurueck.
|
|
|
|
Healthcheck:
|
|
|
|
```csharp
|
|
[Route("isAlive"), HttpGet]
|
|
public IHttpActionResult isAlive()
|
|
{
|
|
return new StatusCodeResult(HttpStatusCode.NoContent);
|
|
}
|
|
```
|
|
|
|
Nicht verwenden:
|
|
|
|
```csharp
|
|
public void isAlive()
|
|
```
|
|
|
|
Symptom:
|
|
|
|
```json
|
|
{"result":null,"parameters":{}}
|
|
```
|
|
|
|
## Null-Rueckgaben
|
|
|
|
Matrix42/Pandora behandelt `null` als fehlerhafte Operation-Response.
|
|
|
|
Symptom:
|
|
|
|
```text
|
|
Method getTicketList returned null
|
|
```
|
|
|
|
Regel:
|
|
|
|
- Listenendpoints geben bei "nichts gefunden" `new List<T>()` zurueck.
|
|
- Objekte geben ein leeres DTO oder 204 zurueck, aber nicht unbewusst `null`.
|
|
- Strings koennen bei Bedarf `string.Empty` statt `null` liefern.
|
|
|
|
## Routen und Parameterbindung
|
|
|
|
Wichtiges spaetes Learning: Der Matrix42 `m42Services`-Gateway kann Query-Parameter auch dann an die Methode binden, wenn die Controller-Route path-basierte Platzhalter hat.
|
|
|
|
Beispiel im Code:
|
|
|
|
```csharp
|
|
[Route("getDirectLinkF4SD/{eoid}/{type}"), HttpGet]
|
|
public async Task<string> getDirectLinkF4SD(Guid eoid, string type)
|
|
```
|
|
|
|
Funktionierende Legacy-URL:
|
|
|
|
```text
|
|
/m42Services/api/c4itf4sdwebapi/getdirectlinkf4sd/?eoid=<guid>&type=user
|
|
```
|
|
|
|
Daraus folgt fuer diese Migration:
|
|
|
|
- Controller nicht doppeln.
|
|
- Keine Query-Helper einbauen.
|
|
- Kein `[FromUri]` als Rettungsversuch verwenden, wenn das Matrix42-Binding ohnehin funktioniert.
|
|
- Die Postman-Collection testet bewusst die alten Query-Routen, damit Client-Kompatibilitaet erhalten bleibt.
|
|
- `PLSLWebServiceOperation.RouteTemplate` darf path-basiert sein, die alten Query-Aufrufe muessen trotzdem getestet werden.
|
|
|
|
Betroffene alte Testformate:
|
|
|
|
```text
|
|
getTicketList?sid=...&hours=...&queueoption=...&queues=...
|
|
getDirectLinkCreateTicket?sid=...&assetname=...
|
|
getDirectLinkF4SD?eoid=...&type=...
|
|
```
|
|
|
|
## Pickups und Enumerations
|
|
|
|
`IEntityDataService.GetEnumeration(...)` ist bequem, zieht aber Pandora-Services herein. Das war fuer reine Pickups zu schwer.
|
|
|
|
Bewaehrt:
|
|
|
|
```csharp
|
|
Matrix42.Persistence.Contracts.IEnumerationProvider
|
|
```
|
|
|
|
Dieser Service kommt ueber `Matrix42.DataLayer.Persistence` und liefert eine `DataTable`. Wenn der alte API-Vertrag `EntityEnumeration` bleiben soll, muss die `DataTable` selbst gemappt werden.
|
|
|
|
Gepruefte Alternativen:
|
|
|
|
- `Matrix42.Pandora.Contracts.IEntityDataService`: liefert direkt `EntityEnumeration`, benoetigt aber Pandora-Module.
|
|
- `update4u.SPS.DataLayer.Contracts.IPickupDataService`: liefert ebenfalls `DataTable`, ohne klaren Vorteil gegenueber `IEnumerationProvider`.
|
|
|
|
Empfehlung:
|
|
|
|
- Fuer reine Pickup-Lesefunktionen `IEnumerationProvider` verwenden.
|
|
- Pandora nur laden, wenn ein Endpoint es wirklich benoetigt.
|
|
|
|
## Aktueller Benutzer
|
|
|
|
`IPandoraUserProfile` nicht im Controller injizieren.
|
|
|
|
Fuer `getMyRoleMemberships` reicht der Matrix42 Principal:
|
|
|
|
```csharp
|
|
var principal = Thread.CurrentPrincipal as IM42Principal;
|
|
var userId = principal?.InteractivePrincipal?.M42Identity?.UserFragmentID
|
|
?? principal?.M42Identity?.UserFragmentID
|
|
?? Guid.Empty;
|
|
```
|
|
|
|
Danach kann der vorhandene ASQL-/Helper-Code mit der `Guid` weiterarbeiten.
|
|
|
|
## Ticket-Historie und Journal
|
|
|
|
Ziel: den Matrix42-Service nutzen, nicht eigene Journal-Logik nachbauen.
|
|
|
|
Finaler Ansatz:
|
|
|
|
- `IJournalService` ueber den Matrix42-Resolver laden.
|
|
- Keine direkte Konstruktion von `JournalService`.
|
|
- Keine eigenen DispatchProxy-/NoOp-Services.
|
|
- Keine HTTP-Weiterleitung an interne Admin-APIs.
|
|
- Keine Storage-Fallback-Journal-Implementierung als finaler Pfad.
|
|
- `GetJournalList` per Reflection gegen die zur Laufzeit vorhandene Signatur aufrufen, weil sich die Signatur zwischen 26.1 Patch-Leveln unterscheiden kann.
|
|
|
|
Warum Reflection hier akzeptiert wurde:
|
|
|
|
- Der alte direkte Compile-Time-MethodRef brach mit `MissingMethodException`.
|
|
- Die geladene Runtime-DLL hatte eine andere `IJournalService.GetJournalList`-Signatur.
|
|
- Die Reflection sucht kompatible Journal-Reader-Methoden und liefert klare Diagnose, wenn keine passende Signatur existiert.
|
|
|
|
Typische Fehler auf dem Weg:
|
|
|
|
```text
|
|
Method not found: IJournalService.GetJournalList(...)
|
|
IJournalService could not be resolved
|
|
IExternalAuthService is an interface and cannot be constructed
|
|
IOAuth2AuthorizeService is an interface and cannot be constructed
|
|
IApiExplorer is an interface and cannot be constructed
|
|
IRequestPropertiesProvider is an interface and cannot be constructed
|
|
IExternalSearchService is an interface and cannot be constructed
|
|
```
|
|
|
|
Learning: Bei diesen Fehlern nicht weiter im Endpoint herumprobieren, sondern die fehlende Host-Registrierung bzw. das passende Matrix42-Modul identifizieren.
|
|
|
|
## Overview-Endpoints
|
|
|
|
`getTicketOverviewCounts` liefert Counts fuer mehrere Keys.
|
|
|
|
`getTicketOverviewRelations` nimmt genau einen `key` und ein `count`.
|
|
|
|
Postman-Learning:
|
|
|
|
- `getTicketOverviewCounts personal` und `getTicketOverviewCounts role` leiten `scope`, `overviewKey` und `overviewRelationExpectedCount` ab.
|
|
- `getTicketOverviewRelations` nutzt diese Variablen.
|
|
- Der Relations-Test erwartet, dass `response.length` dem vorher abgeleiteten Count entspricht.
|
|
- Im normalen Collection-Lauf ueberschreibt `role` die Werte von `personal`, weil `role` nach `personal` ausgefuehrt wird.
|
|
|
|
## Direct Link
|
|
|
|
Fuer F4SD Direct Links ist der Typ in der alten Integration nicht der Matrix42 ActivityType, sondern der F4SD-Typ.
|
|
|
|
Postman setzt deshalb nach `getTicketList`:
|
|
|
|
```javascript
|
|
pm.collectionVariables.set("type", "ticket");
|
|
```
|
|
|
|
`objectType` bleibt separat auf `ticket.ActivityType`, falls der technische Matrix42-Typ fuer andere Tests gebraucht wird.
|
|
|
|
## Postman-Collection
|
|
|
|
Die Collection ist Teil der Migration und Regression.
|
|
|
|
Regeln:
|
|
|
|
- Basic Auth ueber Variablen `basicUsername` und `basicPassword`.
|
|
- `baseUrl` enthaelt `/m42Services`.
|
|
- Legacy-Query-Routen testen, nicht nur neue path-basierte Formen.
|
|
- `getTicketList` zieht `eoid` und `ticketObjectId` aus `TicketObjectId`.
|
|
- `type` fuer Direct Link bleibt `ticket`.
|
|
- `isAlive` erwartet 204 und keinen Body.
|
|
- Allgemeiner Test erkennt versehentlich serialisierte `HttpResponseMessage`-Objekte.
|
|
|
|
## Smoke-Test-Reihenfolge
|
|
|
|
Nach jeder Paketinstallation:
|
|
|
|
1. `GET /m42Services/api/<prefix>/isalive`
|
|
Erwartung: HTTP 204 No Content.
|
|
2. `GET /m42Services/api/<prefix>/getpickup/<PickupName>`
|
|
Erwartung: JSON-Nutzdaten, keine `HttpResponseMessage`-Huelle.
|
|
3. `GET /m42Services/api/<prefix>/getMyRoleMemberships`
|
|
Erwartung: aktueller Benutzer und Rollen, kein `IPandoraUserProfile`-Fehler.
|
|
4. `GET /m42Services/api/<prefix>/getTicketList?...`
|
|
Erwartung: leere Liste oder Tickets, aber kein `returned null`.
|
|
5. Direct Links mit Legacy-Query-Routen.
|
|
6. Overview Counts und Relations.
|
|
7. Journal-/History-Endpoints zuletzt, weil hier die meisten Matrix42-Services transitiv benoetigt werden.
|
|
|
|
## Typische Fehlersymptome
|
|
|
|
```text
|
|
Cannot create instance of <Controller>: The current type, <Interface>, is an interface and cannot be constructed.
|
|
```
|
|
|
|
Meist direkte Konstruktor-Injection oder fehlendes Host-Modul.
|
|
|
|
```text
|
|
Could not load type 'System.Web.Routing.RouteTable'
|
|
```
|
|
|
|
Ungeeignetes altes `System.Web`-/WebApi-Modul in der Sandbox. Ursache entfernen, nicht weitere Alt-Abhaengigkeiten nachladen.
|
|
|
|
```text
|
|
IApiExplorer is an interface and cannot be constructed
|
|
```
|
|
|
|
Sandbox-Host stellt diese WebApi-Explorer-Instanz nicht automatisch bereit. Ueber eigenen `IDependencyRegistrator` registrieren.
|
|
|
|
```json
|
|
{"Version":"1.1","Content":{...},"StatusCode":200}
|
|
```
|
|
|
|
Ein `HttpResponseMessage` wurde als DTO serialisiert. Rueckgabe auf direkten Nutzdatentyp umstellen.
|
|
|
|
```json
|
|
{"result":null,"parameters":{}}
|
|
```
|
|
|
|
Void-Endpoint oder falsch behandelte leere Rueckgabe. Fuer NoContent `StatusCodeResult(HttpStatusCode.NoContent)` nutzen.
|
|
|
|
```text
|
|
Method <name> returned null
|
|
```
|
|
|
|
Endpoint gibt `null` zurueck. Leeres DTO oder leere Liste zurueckgeben.
|
|
|
|
## Verworfene Zwischenansaetze
|
|
|
|
Diese Ansaetze haben nicht nachhaltig geholfen und sollen nicht erneut aufgebaut werden:
|
|
|
|
- Matrix42-Fachinterfaces direkt im Controller-Konstruktor injizieren.
|
|
- Immer mehr Module auf Vorrat laden, ohne die konkrete fehlende Registrierung zu kennen.
|
|
- `HttpResponseMessage` als Datenantwort verwenden.
|
|
- Query-Parameter per eigenem Helper aus `RequestUri` lesen.
|
|
- `[FromUri]` pauschal an alle GET-Parameter setzen.
|
|
- `JournalService` direkt konstruieren.
|
|
- NoOp-/Proxy-Abhaengigkeiten fuer Journal-Services erzeugen.
|
|
- Journal-Historie aus unvollstaendigen Kommentarfeldern nachbauen.
|
|
- Interne Matrix42 Admin-Webservices als finalen Journal-Pfad weiterleiten.
|
|
|
|
## Migrationsablauf fuer weitere Extensions
|
|
|
|
1. Ziel-Commit der Legacy-Funktionalitaet festlegen.
|
|
2. Altes Paket entpacken und IDs dokumentieren.
|
|
3. Herstellerbeispiel/Scaffolder-Struktur als 26.1-Referenz verwenden.
|
|
4. Projekt auf .NET 8 und `Matrix42.WebApi.Contracts.ApiController` umstellen.
|
|
5. Controller-Konstruktor auf minimale Infrastruktur-Services reduzieren.
|
|
6. Host-Konfig minimal starten.
|
|
7. Package-Build in MSBuild integrieren.
|
|
8. AssemblyVersion als einzige Package-Versionsquelle verwenden.
|
|
9. WebAPI-Rueckgaben auf direkte DTOs/Listen umstellen.
|
|
10. `isAlive` auf echten 204 umstellen.
|
|
11. Pickups zuerst ueber schlanke Services loesen.
|
|
12. Komplexe Matrix42-Services erst bei Bedarf laden.
|
|
13. Bei Unity-Fehlern konkrete Implementierung/Registrator suchen.
|
|
14. Postman-Collection fuer alte Client-Routen aufbauen.
|
|
15. Paket installieren, Service synchronisieren und Smoke-Tests ausfuehren.
|
|
16. Erst nach erfolgreicher Kompatibilitaet fachliche Weiterentwicklungen einbringen.
|
|
|
|
## Git- und Datei-Hinweise
|
|
|
|
- Vor Aenderungen `git status` pruefen.
|
|
- Unrelated/untracked Dateien nicht mitcommitten.
|
|
- Textdateien in diesem Repo mit CRLF speichern.
|
|
- `.dat`-Dateien behalten ihren UTF-8-BOM.
|
|
- Controller-/JSON-Dateien ohne unnoetigen BOM lassen.
|
|
- Debug-Build fuer Debugging, Release/Release_signed fuer Auslieferung.
|
|
- Postman-Collection nach JSON-Aenderungen immer parsen/validieren.
|