docs: document final 26.1 migration process
This commit is contained in:
@@ -108,6 +108,28 @@ Beim Portieren eines Legacy-Pakets:
|
||||
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.
|
||||
6. Nach der ersten lauffaehigen Version die Webservice-Operationen in Matrix42 synchronisieren, exportieren und die synchronisierten Contracts in die Paketdateien mergen.
|
||||
|
||||
Wichtiges finales Learning zu Webservice-Operationen:
|
||||
|
||||
- Wenn ein Endpoint nur nach "Service synchronisieren" korrekt funktioniert, sind die `PLSLWebServiceOperation`-Contracts im Paket nicht mehr synchron zum Controller.
|
||||
- Die synchronisierten Operationen exportieren und mit den bestehenden Paketdateien mergen.
|
||||
- Bestehende `PLSLWebServiceOperation.ID`s nicht durch Export-IDs ersetzen, sonst entstehen auf Bestandssystemen doppelte Operationen.
|
||||
- Bestehende `PDRAudienceClass.ID`s ebenfalls erhalten.
|
||||
- Nur fachliche Operation-Felder uebernehmen: `ResponseContract`, `RequestContract`, `Name`, `RouteTemplate`, `SupportedOperation`, `Type`, `IsPublic`.
|
||||
- Neue Operationen, die bisher nicht im Paket vorhanden waren, duerfen die exportierten IDs verwenden, wenn sie aus dem Zielsystem stammen, auf dem sie bereits synchronisiert wurden.
|
||||
- Operation-Dateien nach Operation benennen, z. B. `getticketlist.dat`, `getpickup.dat`, `isalive.dat`. Das erleichtert Reviews und verhindert Verwechslungen mit generischen `02-01-xxxx PLSLWebServiceOperationType.dat`-Dateien.
|
||||
- Jede Datei aus `PackageTemplate/install/0002_WebServiceOperation` muss in `PackageTemplate/install.xml` referenziert sein.
|
||||
|
||||
Validierung:
|
||||
|
||||
```powershell
|
||||
# XML parsebar?
|
||||
python -c "import pathlib,xml.etree.ElementTree as ET; [ET.parse(p) for p in pathlib.Path('PackageTemplate/install/0002_WebServiceOperation').glob('*.dat')]"
|
||||
|
||||
# Debug-Paket bauen und pruefen, ob alle Operation-Dateien im Paket liegen
|
||||
dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Debug
|
||||
```
|
||||
|
||||
Konkretes 26.1-Learning:
|
||||
|
||||
@@ -224,7 +246,7 @@ 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.
|
||||
- `isAlive` gibt `IHttpActionResult` mit einem expliziten HTTP-204-Response zurueck.
|
||||
|
||||
Healthcheck:
|
||||
|
||||
@@ -232,7 +254,13 @@ Healthcheck:
|
||||
[Route("isAlive"), HttpGet]
|
||||
public IHttpActionResult isAlive()
|
||||
{
|
||||
return new StatusCodeResult(HttpStatusCode.NoContent);
|
||||
var response = new HttpResponseMessage(HttpStatusCode.NoContent)
|
||||
{
|
||||
RequestMessage = Request
|
||||
};
|
||||
response.Headers.ConnectionClose = true;
|
||||
|
||||
return ResponseMessage(response);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -266,28 +294,63 @@ Regel:
|
||||
|
||||
## 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.
|
||||
Finales Learning: Fuer Legacy-Kompatibilitaet muessen Route, `PLSLWebServiceOperation.RouteTemplate`, `[FromUri]` und die alten Client-URLs zusammen betrachtet werden.
|
||||
|
||||
Beispiel im Code:
|
||||
Bewaehrte Regeln:
|
||||
|
||||
- Die Route-Attribute aus der funktionierenden Legacy-Version uebernehmen.
|
||||
- Query-basierte Legacy-Endpoints bleiben query-basiert, z. B. `[Route("getTicketList")]`.
|
||||
- Path-basierte Legacy-Endpoints bleiben path-basiert, z. B. `[Route("getPickup/{name}")]`.
|
||||
- GET-Parameter mit `[FromUri]` markieren.
|
||||
- Zusaetzlich einen kleinen zentralen Query-Fallback verwenden, weil in 26.1 einzelne optionale Queryparameter trotz `[FromUri]` nicht immer in der Methode ankamen.
|
||||
- Keine doppelten Controller-Methoden fuer alte und neue URL-Formen bauen.
|
||||
- Die Postman-Collection testet bewusst die alten Client-URLs.
|
||||
|
||||
Beispiel Query-Route:
|
||||
|
||||
```csharp
|
||||
[Route("getDirectLinkF4SD/{eoid}/{type}"), HttpGet]
|
||||
public async Task<string> getDirectLinkF4SD(Guid eoid, string type)
|
||||
[Route("getDirectLinkCreateTicket"), HttpGet]
|
||||
public async Task<DirectLink> getDirectLinkCreateTicket(
|
||||
[FromUri] string sid = "",
|
||||
[FromUri] string assetname = "")
|
||||
{
|
||||
sid = QueryValue(sid, nameof(sid));
|
||||
assetname = QueryValue(assetname, nameof(assetname));
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Funktionierende Legacy-URL:
|
||||
Beispiel Path-Route mit zusaetzlichen Queryparametern:
|
||||
|
||||
```text
|
||||
/m42Services/api/c4itf4sdwebapi/getdirectlinkf4sd/?eoid=<guid>&type=user
|
||||
```csharp
|
||||
[Route("getPickup/{name}"), HttpGet]
|
||||
public async Task<EntityEnumeration> getPickup(
|
||||
[FromUri] string name,
|
||||
[FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None,
|
||||
[FromUri] int group = -1)
|
||||
{
|
||||
name = QueryValue(name, nameof(name));
|
||||
mode = QueryValue(mode, nameof(mode));
|
||||
group = QueryValue(group, nameof(group));
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Daraus folgt fuer diese Migration:
|
||||
Der zentrale Query-Fallback ist bewusst klein und verwendet die strukturierte WebAPI-API statt eigenes URL-Parsen:
|
||||
|
||||
- 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.
|
||||
```csharp
|
||||
private string GetQueryValue(string name)
|
||||
{
|
||||
return Request?.GetQueryNameValuePairs()
|
||||
.FirstOrDefault(pair => string.Equals(pair.Key, name, StringComparison.OrdinalIgnoreCase))
|
||||
.Value;
|
||||
}
|
||||
|
||||
private string QueryValue(string value, string name)
|
||||
{
|
||||
return GetQueryValue(name) ?? value ?? string.Empty;
|
||||
}
|
||||
```
|
||||
|
||||
Betroffene alte Testformate:
|
||||
|
||||
@@ -295,6 +358,7 @@ Betroffene alte Testformate:
|
||||
getTicketList?sid=...&hours=...&queueoption=...&queues=...
|
||||
getDirectLinkCreateTicket?sid=...&assetname=...
|
||||
getDirectLinkF4SD?eoid=...&type=...
|
||||
getPickup/<name>?mode=...&group=...
|
||||
```
|
||||
|
||||
## Pickups und Enumerations
|
||||
@@ -452,7 +516,7 @@ Ein `HttpResponseMessage` wurde als DTO serialisiert. Rueckgabe auf direkten Nut
|
||||
{"result":null,"parameters":{}}
|
||||
```
|
||||
|
||||
Void-Endpoint oder falsch behandelte leere Rueckgabe. Fuer NoContent `StatusCodeResult(HttpStatusCode.NoContent)` nutzen.
|
||||
Void-Endpoint oder falsch behandelte leere Rueckgabe. Fuer NoContent einen `IHttpActionResult` mit HTTP 204 liefern.
|
||||
|
||||
```text
|
||||
Method <name> returned null
|
||||
@@ -468,7 +532,7 @@ Diese Ansaetze haben nicht nachhaltig geholfen und sollen nicht erneut aufgebaut
|
||||
- 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.
|
||||
- Doppelte Controller-Methoden fuer alte Query-URLs und neue Path-URLs bauen.
|
||||
- `JournalService` direkt konstruieren.
|
||||
- NoOp-/Proxy-Abhaengigkeiten fuer Journal-Services erzeugen.
|
||||
- Journal-Historie aus unvollstaendigen Kommentarfeldern nachbauen.
|
||||
@@ -486,12 +550,17 @@ Diese Ansaetze haben nicht nachhaltig geholfen und sollen nicht erneut aufgebaut
|
||||
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.
|
||||
11. Controller-Routen aus der funktionierenden Legacy-Version uebernehmen.
|
||||
12. GET-Parameter mit `[FromUri]` versehen und fehlende Querywerte zentral ueber `Request.GetQueryNameValuePairs()` nachziehen.
|
||||
13. Pickups zuerst ueber schlanke Services loesen.
|
||||
14. Komplexe Matrix42-Services erst bei Bedarf laden.
|
||||
15. Bei Unity-Fehlern konkrete Implementierung/Registrator suchen.
|
||||
16. Webservice-Operationen nach erfolgreicher Installation in Matrix42 synchronisieren.
|
||||
17. Synchronisierte Operationen exportieren und in die Paketdateien mergen, ohne bestehende IDs zu ersetzen.
|
||||
18. Operation-Dateien sprechend nach Operation benennen und in `install.xml` referenzieren.
|
||||
19. Postman-Collection fuer alte Client-Routen aufbauen.
|
||||
20. Paket installieren, Service synchronisieren und Smoke-Tests ausfuehren.
|
||||
21. Erst nach erfolgreicher Kompatibilitaet fachliche Weiterentwicklungen einbringen.
|
||||
|
||||
## Git- und Datei-Hinweise
|
||||
|
||||
|
||||
Reference in New Issue
Block a user