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.
|
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.
|
4. Operation-IDs nur dann aendern, wenn bewusst neue Operationen entstehen sollen.
|
||||||
5. Obsolete oder entfernte Schema-Attribute aus 26.1 entfernen.
|
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:
|
Konkretes 26.1-Learning:
|
||||||
|
|
||||||
@@ -224,7 +246,7 @@ Bewaehrt:
|
|||||||
|
|
||||||
- Datenendpoints geben direkte Nutzdaten zurueck, z. B. `Task<List<T>>`, `Task<object>` oder `Task<EntityEnumeration>`.
|
- Datenendpoints geben direkte Nutzdaten zurueck, z. B. `Task<List<T>>`, `Task<object>` oder `Task<EntityEnumeration>`.
|
||||||
- Leere Listen duerfen nicht `null` sein.
|
- 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:
|
Healthcheck:
|
||||||
|
|
||||||
@@ -232,7 +254,13 @@ Healthcheck:
|
|||||||
[Route("isAlive"), HttpGet]
|
[Route("isAlive"), HttpGet]
|
||||||
public IHttpActionResult isAlive()
|
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
|
## 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
|
```csharp
|
||||||
[Route("getDirectLinkF4SD/{eoid}/{type}"), HttpGet]
|
[Route("getDirectLinkCreateTicket"), HttpGet]
|
||||||
public async Task<string> getDirectLinkF4SD(Guid eoid, string type)
|
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
|
```csharp
|
||||||
/m42Services/api/c4itf4sdwebapi/getdirectlinkf4sd/?eoid=<guid>&type=user
|
[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.
|
```csharp
|
||||||
- Keine Query-Helper einbauen.
|
private string GetQueryValue(string name)
|
||||||
- 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.
|
return Request?.GetQueryNameValuePairs()
|
||||||
- `PLSLWebServiceOperation.RouteTemplate` darf path-basiert sein, die alten Query-Aufrufe muessen trotzdem getestet werden.
|
.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:
|
Betroffene alte Testformate:
|
||||||
|
|
||||||
@@ -295,6 +358,7 @@ Betroffene alte Testformate:
|
|||||||
getTicketList?sid=...&hours=...&queueoption=...&queues=...
|
getTicketList?sid=...&hours=...&queueoption=...&queues=...
|
||||||
getDirectLinkCreateTicket?sid=...&assetname=...
|
getDirectLinkCreateTicket?sid=...&assetname=...
|
||||||
getDirectLinkF4SD?eoid=...&type=...
|
getDirectLinkF4SD?eoid=...&type=...
|
||||||
|
getPickup/<name>?mode=...&group=...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pickups und Enumerations
|
## Pickups und Enumerations
|
||||||
@@ -452,7 +516,7 @@ Ein `HttpResponseMessage` wurde als DTO serialisiert. Rueckgabe auf direkten Nut
|
|||||||
{"result":null,"parameters":{}}
|
{"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
|
```text
|
||||||
Method <name> returned null
|
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.
|
- Immer mehr Module auf Vorrat laden, ohne die konkrete fehlende Registrierung zu kennen.
|
||||||
- `HttpResponseMessage` als Datenantwort verwenden.
|
- `HttpResponseMessage` als Datenantwort verwenden.
|
||||||
- Query-Parameter per eigenem Helper aus `RequestUri` lesen.
|
- 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.
|
- `JournalService` direkt konstruieren.
|
||||||
- NoOp-/Proxy-Abhaengigkeiten fuer Journal-Services erzeugen.
|
- NoOp-/Proxy-Abhaengigkeiten fuer Journal-Services erzeugen.
|
||||||
- Journal-Historie aus unvollstaendigen Kommentarfeldern nachbauen.
|
- 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.
|
8. AssemblyVersion als einzige Package-Versionsquelle verwenden.
|
||||||
9. WebAPI-Rueckgaben auf direkte DTOs/Listen umstellen.
|
9. WebAPI-Rueckgaben auf direkte DTOs/Listen umstellen.
|
||||||
10. `isAlive` auf echten 204 umstellen.
|
10. `isAlive` auf echten 204 umstellen.
|
||||||
11. Pickups zuerst ueber schlanke Services loesen.
|
11. Controller-Routen aus der funktionierenden Legacy-Version uebernehmen.
|
||||||
12. Komplexe Matrix42-Services erst bei Bedarf laden.
|
12. GET-Parameter mit `[FromUri]` versehen und fehlende Querywerte zentral ueber `Request.GetQueryNameValuePairs()` nachziehen.
|
||||||
13. Bei Unity-Fehlern konkrete Implementierung/Registrator suchen.
|
13. Pickups zuerst ueber schlanke Services loesen.
|
||||||
14. Postman-Collection fuer alte Client-Routen aufbauen.
|
14. Komplexe Matrix42-Services erst bei Bedarf laden.
|
||||||
15. Paket installieren, Service synchronisieren und Smoke-Tests ausfuehren.
|
15. Bei Unity-Fehlern konkrete Implementierung/Registrator suchen.
|
||||||
16. Erst nach erfolgreicher Kompatibilitaet fachliche Weiterentwicklungen einbringen.
|
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
|
## Git- und Datei-Hinweise
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user