Become a member!

DelphiMVCFramework 3.5 RC7 entre dans le Project Manager de Delphi et parle aux agents IA

🌐
Cet article est aussi disponible dans d'autres langues :
🇬🇧 English  •  🇮🇹 Italiano  •  🇪🇸 Español  •  🇩🇪 Deutsch  •  🇧🇷 Português

DelphiMVCFramework, le framework open source REST et web pour Delphi

Qu'est-ce qui a changé dans DelphiMVCFramework après la RC6 ? Le travail sur la 3.5 s'est concentré sur la façon dont tu crées un projet et dont tu le fais grandir, dans l'IDE de Delphi et avec les agents IA. Cette fois, je te le montre en captures d'écran.

DelphiMVCFramework 3.5.0-silicon RC7 est une release candidate, pas la 3.5.0 définitive : les fonctionnalités sont celles que tu vois ici, et le tag stable arrivera quand la RC aura tourné sur d’autres machines que la mienne.

La RC6 date du 23 août, et le post qui l’annonçait parlait d’hosts, de Minimal API et de sérialiseur en streaming. La RC7 est sortie le 22 septembre. Ensuite, sur master, sont arrivées deux nouveautés pour le travail de tous les jours sur un projet. Un menu DMVCFramework dans le Project Manager de Delphi crée des controllers, des groupes de routes et des vues, et les enregistre dans le projet. Les fichiers pour les agents IA donnent à ton assistant les règles et les sources du framework, pour qu’il n’écrive pas l’API de mémoire. Et puis il y a le reste : Swagger UI avec OpenAPI 3, les pages web générées, QUERY, ProblemDetails.

Voici un tour rapide, presque tout en images. Chaque sujet a son chapitre dans le guide officiel, deuxième édition, avec le code complet et les explications que je saute dans ce post.


Où trouver quoi

Tout ce que tu vois ici appartient à la RC7 : c’est la version que le wizard écrit dans les projets générés (3.5.0-silicon-rc7, tu la vois aussi dans les captures). Mais une partie n’est pas encore dans le zip du tag :

  • Dans la RC7 (tag v3.5.0-silicon-rc7) : la méthode HTTP QUERY, la revue de sécurité avec ses nouveaux défauts, les limites du serveur WebSocket, les corrections pour HTTP.sys, SQL Server et Delphi 13.2.
  • Sur master, après la RC7 : tout le reste. Le menu dans le Project Manager, les fichiers pour les agents IA, le wizard avec OpenAPI 3, les pages web générées, le sample avec les formulaires, ProblemDetails. Pour les avoir, clone master.

Les captures ci-dessous viennent de master.


Un menu DMVCFramework dans le Project Manager

Dans Delphi 12 et 13, clic droit sur un projet DelphiMVCFramework dans le Project Manager, et il y a un sous-menu DMVCFramework :

Le menu DMVCFramework dans le Project Manager de Delphi 13, avec l’entrée New REST Controller

Choisis New REST Controller…, écris le nom, et le reste se remplit tout seul : le segment d’URL et la classe du modèle à laquelle est lié le body des requêtes.

La fenêtre New REST controller avec Name Orders, URL segment orders et Model class TOrder

Clique sur OK et le menu crée Controllers.OrdersU.pas, l’ajoute au projet et l’enregistre dans EngineConfigU.pas : l’unit dans la uses et AEngine.AddController(TOrdersController) à côté des autres controllers. Les modifications passent par le buffer de l’éditeur, donc un Ctrl+Z les annule.

EngineConfigU.pas dans l’IDE après l’insertion de Controllers.OrdersU dans la uses

Voici le controller généré, tel qu’il sort du menu dans un projet où la documentation OpenAPI est active :

type
  TOrder = class
  private
    fID: Integer;
    fName: string;
  public
    property ID: Integer read fID write fID;
    [MVCRequired]
    property Name: string read fName write fName;
  end;

  [MVCPath('/api/orders')]
  [MVCSWAGDefaultModel(TOrder, 'Order', 'Orders')]
  [MVCSWAGDefaultSummaryTags('Orders')]
  TOrdersController = class(TMVCController)
  public
    [MVCPath]
    [MVCHTTPMethod([httpGET])]
    [MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'List orders', 'getOrders')]
    // last argument: OkResponse renders the body as {"data": ...}
    [MVCSwagResponses(200, 'Success', SWAGUseDefaultControllerModel, True, True)]
    function GetAll: IMVCResponse;

    [MVCPath('/($ID:int)')]
    [MVCHTTPMethod([httpGET])]
    [MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Get one', 'getOrder')]
    [MVCSwagResponses(200, 'Success', SWAGUseDefaultControllerModel, False, True)]
    [MVCSwagResponses(404, 'Not found')]
    function GetByID(ID: Integer): IMVCResponse;

    // the body is bound to Item and validated (422 on failure); the framework frees it
    [MVCPath]
    [MVCHTTPMethod([httpPOST])]
    [MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Create', 'createOrder')]
    [MVCSwagParam(plBody, 'Item', 'The item to create', SWAGUseDefaultControllerModel)]
    [MVCSwagResponses(201, 'Created')]
    [MVCSwagResponses(422, 'Validation failed')]
    function CreateItem([MVCFromBody] Item: TOrder): IMVCResponse;
    ...

Le body arrive déjà désérialisé dans Item et déjà validé : sans name, la requête n’entre même pas dans l’action et le client reçoit un 422. Le schéma des réponses vient de la classe du modèle : avec le dernier argument de MVCSwagResponses, le document décrit aussi l’enveloppe {"data": ...} qu’ajoute OkResponse. Les attributs MVCSwag* ne sont là que si le projet publie un document OpenAPI, et c’est pour ça que Orders et son modèle apparaissent dans Swagger UI sans que j’aie écrit une ligne : tu le vois plus bas.

Le menu ne montre que ce que le projet peut accueillir. Dans un projet Minimal API, le controller n’aurait pas de sens, et l’entrée proposée est donc différente :

Le menu DMVCFramework dans un projet Minimal API, avec l’entrée New Minimal API Route Group

New Minimal API Route Group… crée OrdersRoutesU.pas avec une procédure MapOrdersRoutes (bodies liés par type avec MapPost<TOrder> et MapPut<Integer, TOrder>) et ajoute l’appel à la fin de ConfigureRoutes. Les deux autres entrées sont New Web Controller and View… et New TemplatePro View…, et elles n’apparaissent que si le projet a un dossier de vues. Dans les versions de Delphi antérieures à la 12, le menu n’existe pas.


Un projet qui naît avec les bonnes skills

Si tu écris du code avec Claude Code, Codex, Cursor ou Gemini, un agent qui ne connaît pas DelphiMVCFramework invente des noms de méthodes plausibles, ou bien utilise ceux d’une vieille version, et le compilateur ne te le dit qu’après.

Avec la RC7, chaque nouveau projet DelphiMVCFramework naît déjà prêt pour l’agent : le wizard y met les skills adaptées à ce type de projet, prises dans la même ligne du framework que celle que tu utilises. Ce sont les bonnes pratiques écrites pour ceux qui développent avec DelphiMVCFramework, réparties par sujet :

  • Delphi : le langage et la RTL, les différences entre versions, la gestion de la mémoire, chaînes, generics, threads ; plus une skill de code review sur les warnings, l’analyse statique et les fuites mémoire.
  • DelphiMVCFramework : controllers, ActiveRecord, validation, injection de dépendances, middleware, les trois hosts, .env.
  • Sécurité : les règles pour chaque endpoint qui reçoit des données du client.
  • Tests : tests d’intégration avec DUnitX.
  • Minimal API, web application, interface, JSON-RPC : quand le projet les utilise.
  • HTMX : la documentation officielle, organisée pour l’agent.

L’avantage, tu le vois dès la première demande. Sans skills et sans AGENTS.md, chaque session avec l’agent commence par lui expliquer le projet et le framework, et continue en corrigeant le code qu’il a écrit de mémoire : une méthode qui n’existe pas, un pattern d’une vieille version, un objet libéré deux fois. Avec le projet généré par le wizard, l’agent sait déjà comment le projet est fait, où se trouvent les sources du framework et comment on écrit un controller, une entité ActiveRecord ou une page HTMX en DelphiMVCFramework 3.5. Ce temps, tu le gagnes à chaque session.

Il y a aussi la sécurité. Parmi les skills installées dans chaque projet, il y a dmvcframework-security, avec les règles pour tout endpoint qui reçoit des données du client : contrôle d’accès, mass assignment, injection SQL, XSS, CSRF, path traversal et uploads, JWT, secrets et messages d’erreur, plus une checklist à passer avant qu’un endpoint parte en production. L’agent la lit avant d’écrire un endpoint, donc le code que tu obtiens a tendance à être plus sûr que celui qu’il écrirait en partant de zéro.

Les skills vivent dans un dépôt à part, avec une branche pour chaque ligne du framework, et se mettent à jour indépendamment des releases : quand une nouvelle version d’une skill sort, update_ai_skills.bat dans le dossier du projet la récupère.

L’option se trouve dans la page Project Options, AI coding agent files and skills, et elle est active par défaut dans tous les presets. Les skills sont téléchargées pendant que le wizard crée le projet, avec une barre de progression que tu peux annuler ; si tu n’en as pas besoin, décoche-la.

La page Project Options du wizard avec l’option AI coding agent files and skills

Avec l’option cochée, le wizard écrit dans le dossier du projet un AGENTS.md avec les informations de base du projet, plus CLAUDE.md et GEMINI.md qui l’importent. Puis il télécharge dans .claude\skills les delphi-ai-skills adaptées à ce type de projet, depuis la branche qui correspond à la version du framework (dmvc-3.5 pour celle-ci). Voici l’AGENTS.md d’un projet RESTful API généré par la suite de tests du wizard, qui l’appelle TestProject :

# TestProject

DelphiMVCFramework 3.5.0-silicon-rc7 project, generated by the DMVCFramework IDE wizard.

- `TestProject.dproj` builds the executable into `bin\`, next to `bin\.env` (configuration and secrets: never commit real values).
- Build from the command line: `rsvars.bat`, then `msbuild TestProject.dproj /p:Config=Debug /p:Platform=Win32`.

## Skills

Before writing Delphi or DelphiMVCFramework code, read the skill for the task. They target DelphiMVCFramework 3.5.x; `update_ai_skills.bat` downloads or refreshes them.

- `.claude/skills/delphi/SKILL.md` - the language and the RTL: version gating, lifetime, strings, generics, threading
- `.claude/skills/delphi-code-smells/SKILL.md` - code review: compiler warnings, static analysis, memory leaks
- `.claude/skills/dmvcframework/SKILL.md` - controllers, ActiveRecord, validation, DI, middleware, servers, dotEnv
- `.claude/skills/dmvcframework-security/SKILL.md` - REQUIRED for any endpoint taking client input
- `.claude/skills/dmvcframework-testing/SKILL.md` - DUnitX integration tests

Do not write Delphi or DelphiMVCFramework code from memory: the API names in these files are authoritative.

<!-- delphi-local-sources -->
DelphiMVCFramework checkout: C:\DEV\dmvcframework   (sources/ + samples/)
Delphi RTL/VCL source: C:\Program Files (x86)\Embarcadero\Studio\37.0\source   (CompilerVersion 37.0)
<!-- /delphi-local-sources -->

Le dernier bloc dit à l’agent où se trouvent, sur ton disque, les sources du framework et de la RTL : quand il a un doute sur un nom, il va lire le vrai code.

Les skills installées dépendent du projet. delphi, delphi-code-smells, dmvcframework, dmvcframework-security et dmvcframework-testing sont toujours là ; un projet Minimal API ajoute dmvcframework-minimal-api, une web application dmvcframework-webapp et dmvcframework-ui, avec HTMX aussi htmx-skill, un service JSON-RPC dmvcframework-jsonrpc. Si le téléchargement échoue pendant la création, le projet est créé quand même, avec un warning, et update_ai_skills.bat termine l’installation dès que le réseau est disponible.


Le wizard : documentation API et clé JWT

Dans la page Features du preset Custom, il y a une nouvelle option, API documentation (OpenAPI 3). Dans les autres presets, tu ne la vois pas parce que le choix est déjà fait : elle est active pour RESTful API, Minimal API RESTful et Full-Stack.

La page Features du wizard DelphiMVCFramework avec l’option API documentation (OpenAPI 3)

Avec l’option active, le wizard télécharge la release officielle de Swagger UI (5.33.0, vérifiée avec SHA-256) dans bin\www\swagger pendant qu’il crée le projet. Si tu es hors ligne, le projet est créé quand même et dans ce dossier tu trouves un README avec les étapes pour la télécharger à la main. Le document n’est publié que si le .env contient dmvc.openapi.enabled=true : le .env généré le contient, celui de production non, et en production la documentation n’est pas exposée.

Les projets avec JWT ont maintenant dans le .env une JWT_SECRET bien à eux, 384 bits issus du générateur cryptographique du système, différente à chaque génération. Le .gitignore généré exclut déjà le .env.


Swagger UI avec OpenAPI 3

Voici le projet généré avec le preset RESTful API, auquel j’ai ajouté le controller Orders avec le menu qu’on vient de voir. Tu le lances, tu ouvres http://localhost:8080/swagger et tu trouves ceci :

Swagger UI qui affiche le document OpenAPI 3 d’un projet DelphiMVCFramework à base de controllers

Le middleware Swagger, celui que tu utilises depuis des années, produit maintenant aussi de l’OpenAPI 3. Le document est construit par SwagDoc, la bibliothèque incluse dans le framework, et le support d’OpenAPI 3 dans SwagDoc a été écrit par Marcelo Jaloto (PR #916) : merci Marcelo ! Le format se choisit avec un nouveau dernier paramètre, ASpecVersion, qui reste Swagger 2.0 par défaut : pour qui met à jour, rien ne change. Le projet généré l’enregistre ainsi :

AEngine.AddMiddleware(TMVCSwaggerMiddleware.Create(AEngine, LSwaggerInfo, '/openapi.json',
  JWT_DEFAULT_DESCRIPTION, False, '', '', '', [psHTTP], False, ssvOpenAPI3));
AEngine.AddMiddleware(TMVCStaticFilesMiddleware.Create('/swagger',
  TPath.Combine(TPath.Combine(AppPath, 'www'), 'swagger')));

Tout ce qui fonctionnait avec Swagger 2.0 fonctionne : sécurité JWT et basic, MVCSwagAuthentication, MVCSWAGDefaultModel, les chemins CRUD de TMVCActiveRecordController. Le schéma JWT est http/bearer, donc dans la fenêtre Authorize tu colles le token tel quel. Le serveur dans le document est relatif, et “Try it out” appelle l’origine qui a servi le document, même derrière un proxy.

L’opération POST /api/orders dans Swagger UI, avec le body requis et les réponses 201 et 422

Dans les projets Minimal API, le wizard enregistre à la place le filtre OpenAPI(...) de MVCFramework.OpenAPI3, qui génère un document OpenAPI 3.1 à partir des routes lambda et le publie à la même URL, avec la même Swagger UI.

Les champs TDate, TDateTime et TTime sont maintenant décrits avec les formats standard date, date-time et time, donc un client régénéré à partir du document obtient des types date au lieu de chaînes (cela aussi vient de la PR de Marcelo). Les attributs de documentation des champs s’appellent maintenant tous MVCSwag* : MVCFormat, MVCMinimum et MVCMaximum compilent encore, avec un warning, jusqu’à la 4.0.


Les web applications générées

Le preset Web Application part maintenant d’une interface plus complète : en-tête de page, un panneau avec l’état du serveur mis à jour via HTMX, une liste “Start here” avec les premiers pas, thème clair et sombre. Le code généré reste pourtant le minimum : l’exemple avec tableau et formulaires a été déplacé dans un sample à part, dont je parle plus bas.

La page d’accueil d’une web application DelphiMVCFramework générée par le wizard, thème sombre

La même page d’accueil avec le thème clair

Le preset Minimal API WebApp génère les mêmes pages, avec les routes lambda à la place des controllers. Ci-dessous, la page de login après une tentative ratée : le nom d’utilisateur reste dans le champ, le mot de passe non. Le formulaire est lié à une classe, et la page le réaffiche à partir de là.

La page de login d’une Minimal API WebApp après des identifiants erronés


Tableaux et formulaires avec HTMX : webapp_htmx_forms

L’exemple du tableau People, qui était avant dans le projet généré, est devenu un sample à part entière : samples/webapp_htmx_forms. Il contient la recherche, les filtres, le tri et les formulaires complets, sans alourdir chaque nouveau projet.

On peut filtrer le tableau, y faire une recherche et le trier par colonne. Avec HTMX, le serveur ne renvoie que le fragment du tableau et la page ne se recharge pas ; l’action décide d’envoyer la page entière ou le fragment, et définit Vary: HX-Request parce que la même URL a deux bodies différents.

Le tableau People du sample webapp_htmx_forms filtré avec la recherche analyst

Les formulaires de création et de modification utilisent toutes les macros de la bibliothèque de formulaires de TemplatePro (bin/templates/lib/forms_bootstrap5.tpro, que le wizard copie dans chaque projet TemplatePro) et sont validés côté serveur avec les attributs de DelphiMVCFramework et TMVCValidationEngine. Si quelque chose ne va pas, le formulaire revient avec le statut 422, les valeurs que tu as saisies et le message à côté du champ. Si tout va bien, redirection vers le tableau (Post/Redirect/Get), comme ça un F5 ne renvoie pas le formulaire.

Le formulaire New person réaffiché avec des erreurs de validation sur Name et Joined

Côté TemplatePro, le cache des vues compilées vit maintenant en mémoire : avec view_cache=true, après la première requête une vue ne touche plus le disque. Si tu les modifies pendant que le serveur tourne, dmvc.view_cache_check_changes=true rétablit la vérification à chaque requête, layouts et partials compris.


Formulaires générés avec TemplatePro

Le formulaire de la capture ci-dessus vient de la bibliothèque de formulaires de TemplatePro, forms_bootstrap5.tpro, que le wizard copie dans bin/templates/lib dans chaque projet avec des vues TemplatePro. Tu l’importes une fois en haut de la page et tu as huit macros : form, input, textarea, select, checkbox, submit, actions et auto.

{{import "../lib/forms_bootstrap5.tpro" as f}}
{{call f.form(form_action)}}
{{>f.input("id", label="ID", readonly=true)}}
{{>f.input("name", label="Name", required=true)}}
{{>f.select("role", roles, label="Role", empty="Choose a role")}}
{{>f.input("projects", type="number", append="active")}}
{{>f.textarea("notes", label="Notes", rows=3)}}
{{>f.checkbox("remote", label="Works remotely")}}
{{>f.submit("Save")}}
{{endcall}}

Chaque macro lit la valeur du champ dans formModel et le message d’erreur dans formErrors, deux variables que tu définis dans l’action. Le modèle peut être un objet, l’enregistrement courant d’un dataset, un objet JSON ou un dictionnaire. S’il y a une erreur pour ce champ, le contrôle prend la classe is-invalid et le message apparaît dessous : c’est ce que tu vois dans le formulaire réaffiché avec le 422. Valeurs et messages sont toujours HTML-escaped, les dates sont formatées pour les contrôles date, time et datetime-local, et avec attrs tu passes une map d’attributs supplémentaires, par exemple ceux d’HTMX. La même page sert à créer et à modifier : seuls le modèle et l’action changent.

Puis il y a auto, qui génère tout le formulaire tout seul :

{{call f.form("/forms", attrs=formattrs)}}
  {{>f.auto(demo)}}
  {{>f.submit("Save")}}
{{endcall}}

Un formulaire généré par f.auto à partir des propriétés d’un objet Delphi

auto parcourt les champs du modèle (model.@@fields : les propriétés d’un objet ou les champs d’un dataset) et choisit le contrôle d’après le type. Une chaîne devient un champ texte avec un maxlength tiré de la taille, un entier un champ numérique, un TDate un date picker, un TDateTime un datetime-local, un TTime un champ heure, un Boolean une checkbox, un memo une textarea. Une propriété sans setter devient readonly. Le libellé vient du nom : FullName devient “Full name”. Avec exclude, tu retires les champs que tu ne veux pas afficher.

Si le modèle est une entité TMVCActiveRecord, ajoute à la uses l’unit MVCFramework.View.Renderers.TemplatePro.ActiveRecord (le wizard le fait tout seul dans les projets avec ActiveRecord et TemplatePro). À partir de là, les champs suivent le mapping d’ActiveRecord et les validateurs : [MVCRequired] devient l’attribut required, [MVCMaxLength(n)] devient maxlength. Pour tout le reste, il y a TTProConfiguration.OnGetFieldMetadata, qui te permet de changer le libellé, le type, la visibilité et le caractère obligatoire de chaque champ. Le formulaire complet avec toutes les macros se trouve dans la page /forms du sample samples/wizard_showcase/web.


ProblemDetails plus fidèle à la RFC 7807

Les réponses de ProblemDetails(...) suivent maintenant la RFC 7807 de plus près : le problem object est le body entier et le Content-Type est application/problem+json. Le 422 de la Minimal API a en plus un membre errors, avec le message pour chaque champ.

Voici le groupe de routes Orders généré par le menu, dans un projet Minimal API : un POST sans name, puis un POST avec un tableau à la place de l’objet.

$ curl -s -i -X POST http://localhost:8080/api/orders -H "Content-Type: application/json" -d "{\"id\":7}"
HTTP/1.1 422 Unprocessable Entity
Connection: keep-alive
Content-Type: application/problem+json; charset=UTF-8
Content-Length: 176
Date: Mon, 05 Oct 2026 15:22:03 GMT

{"type":"about:blank","title":"Unprocessable Content","status":422,"detail":"Validation failed for fields: Name","instance":"/api/orders","errors":{"Name":"Field is required"}}

$ curl -s -i -X POST http://localhost:8080/api/orders -H "Content-Type: application/json" -d "[1,2]"
HTTP/1.1 400 Bad Request
Connection: keep-alive
Content-Type: application/problem+json; charset=UTF-8
Content-Length: 163
Date: Mon, 05 Oct 2026 15:22:03 GMT

{"type":"about:blank","title":"Bad Request","status":400,"detail":"Body is not a valid JSON Object - Expected TJsonObject got TJsonArray","instance":"/api/orders"}

Un tableau là où il faut un objet est une erreur du client, donc la réponse est un 400, aussi bien dans les controllers avec [MVCFromBody] que dans la Minimal API.


La méthode HTTP QUERY

QUERY (RFC 10008) est sûre et idempotente comme GET, mais elle a un body : la recherche voyage dans le payload, pas dans l’URL, donc elle n’a pas de limite de longueur et ne finit ni dans les logs d’accès, ni dans les caches des proxies, ni dans l’historique du navigateur. J’en ai parlé en détail dans un post dédié (en anglais). Dans la RC7, tu la trouves dans les controllers, dans la Minimal API (MapQuery) et dans IMVCRESTClient (Query).

Le sample samples/routing fait la même recherche deux fois, avec GET et avec QUERY :

[MVCHTTPMethod([httpQUERY])]
[MVCPath('/customers/searches')]
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
function SearchCustomersUsingQuery(
  const [MVCFromBody] Criteria: TCustomerSearch): TObjectList<TPerson>;
$ curl -s -i -X QUERY http://localhost:8080/api/customers/searches -H "Content-Type: application/json" -d "{\"searchtext\":\"rossi\",\"cities\":[\"rome\",\"milan\"],\"pricerange\":{\"min\":10,\"max\":90},\"orderby\":\"lastname\",\"page\":2}"
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json; charset=utf-8
Content-Length: 226
Date: Mon, 05 Oct 2026 17:22:01 GMT
Server: DMVCFramework
X-Powered-By: DMVCFramework 3.5.0-silicon-rc7

[{"firstname":"Daniele","lastname":"Teti","dob":"1975-05-02","married":false},{"firstname":"John","lastname":"Doe","dob":"1975-05-02","married":false},{"firstname":"Mark","lastname":"Rossi","dob":"1975-05-02","married":false}]

Avant de la mettre en production : pour le CSRF, traite-la comme POST, pas comme GET. Le défaut de Access-Control-Allow-Methods du filtre CORS ne l’inclut pas, et si un navigateur d’une autre origine doit l’appeler, tu dois passer la liste complète. Et elle n’apparaît pas dans le document Swagger/OpenAPI : le slot query n’existe que dans OpenAPI 3.2, et le framework omet le verbe au lieu d’écrire un document non valide.


Sécurité : des défauts plus sûrs

La RC7 contient une revue de sécurité de la branche 3.5, et certains défauts sont maintenant plus sûrs. Si tu mets à jour depuis une version précédente, voici ceux à connaître :

  • X-HTTP-Method-Override n’est plus supporté. Réécrire le verbe d’une requête, c’est le travail du reverse proxy ou du serveur web placé devant l’application.
  • IMVCRESTClient et TMVCSSEClient n’acceptent que des certificats valides. Pour un test contre un host avec un certificat self-signed, il y a MVCRESTClientAcceptInvalidCertificates := True.
  • Le cookie de session est HttpOnly par défaut, et depuis Delphi 11 il a SameSite=Lax. Secure est un nouveau paramètre, désactivé par défaut parce que l’activer casserait toute configuration de développement en HTTP ; les projets générés le lisent dans SESSION_COOKIE_SECURE du .env.
  • Au-delà de max_request_size, la réponse est 413 sur tous les hosts, avec le même comportement sur Indy, HTTP.sys et WebBroker.
  • Plus de protection contre les JSON malveillants : le parser refuse les documents construits pour mettre le serveur en difficulté.
  • [MVCMaxLength(n)] et [MVCPattern(...)] valident toujours, quel que soit l’ordre des units dans la uses. Ça, c’est sur master : si tu as des modèles avec ces attributs, après la mise à jour tu les trouves validés.

La liste complète, avec la raison de chaque modification, est dans la section Security du changelog.


Le reste, en bref

  • Routes contrôlées à l’enregistrement. Les types des paramètres (int, int64, float, bool, guid, date, time, datetime, sqids) viennent d’une seule fonction pour les controllers et pour la Minimal API ; time et datetime n’acceptent que l’ISO 8601 et se lient à des paramètres TTime et TDateTime. Un type inconnu, un paramètre sans nom ou un catch-all mal placé font échouer l’enregistrement : le serveur ne démarre pas, au lieu de répondre 404 pour toujours à une route mal écrite.
  • Le body peut être renvoyé dans la réponse. Result := OkResponse(Person) avec [MVCFromBody] Person, ou Ok(Item) dans la Minimal API : la réponse prend l’objet en charge et le libère après le rendu.
  • HTTP.sys répond à PATCH, SEARCH et aux autres verbes que le kernel n’interprète pas tout seul.
  • Serveur WebSocket : quatre limites configurables sur le handshake et la taille des frames, actives par défaut (PR #915).
  • SQL Server : foRefresh renvoie la ligne après les triggers, Insert et Update fonctionnent sur des tables avec triggers, le verrouillage optimiste est détecté même derrière un trigger sans SET NOCOUNT ON (diagnostic de Flavio Basile).
  • Delphi 13.2 : le framework compile aussi sur la dernière mise à jour de Delphi 13 (#917).
  • TemplatePro accepte plus de types de champs des datasets et n’affiche plus comme négatives les grandes valeurs unsigned (contribution de Patrick Premartin).

Sur Patreon : articles et vidéos sur ces fonctionnalités

Pour les supporters sur Patreon, il y aura des articles et des vidéos consacrés justement à ces nouveautés : le menu du Project Manager, les skills pour les agents IA, la documentation OpenAPI générée. Comment les utiliser dans le travail de tous les jours, étape par étape.

Si tu utilises DelphiMVCFramework à titre professionnel, je te demande de soutenir le projet. C’est un investissement pour ton business : le framework sur lequel tu travailles continue de grandir, et en tant que supporter tu peux orienter ses prochains développements. En plus, tu as accès aux contenus de formation dédiés, aux groupes Discord réservés avec un support privilégié et au support prioritaire par email.


Pour l’essayer

Pour la RC7, télécharge le zip depuis la page de release et ajoute sources au library path. Pour tout le reste, clone master et installe le package dmvcframeworkDT de ta version de Delphi : les presets apparaissent dans File > New > Other, sous Delphi > DelphiMVCFramework, et le menu dans le Project Manager arrive avec le même package.

Si quelque chose ne colle pas, ouvre une issue sur GitHub. On est encore en phase de release candidate, et c’est maintenant qu’un signalement devient une correction dans la 3.5.0.


Ressources

PATREON Community

Enjoy!

– Daniele Teti

Faits clés
  • Sujet : les nouveautés de DelphiMVCFramework 3.5.0-silicon après la RC6 (23 août 2026) : la RC7 (tag v3.5.0-silicon-rc7, 22 septembre 2026) et ce qui est sur master au 5 octobre 2026 (même version, 3.5.0-silicon-rc7). C'est une release candidate, pas la 3.5.0 définitive.
  • Dans la RC7 : méthode HTTP QUERY (RFC 10008) avec [MVCHTTPMethod([httpQUERY])], MapQuery dans la Minimal API et Query dans IMVCRESTClient ; HTTP.sys arrête de traiter SEARCH et d'autres verbes comme GET ; une revue de sécurité avec de nouveaux défauts (session HttpOnly, 413 sur chaque host au-delà de max_request_size, protection contre les JSON malveillants, X-HTTP-Method-Override ignoré, certificats non valides refusés par IMVCRESTClient) ; limites sur le serveur WebSocket ; corrections pour SQL Server et pour Delphi 13.2.
  • Sur master après la RC7 : OpenAPI 3 depuis le middleware Swagger (ssvOpenAPI3), option "API documentation (OpenAPI 3)" dans le wizard avec Swagger UI 5.33.0 téléchargée à la création du projet et publiée sur /swagger quand le .env définit dmvc.openapi.enabled=true ; clé JWT générée dans le .env ; fichiers pour agents IA (AGENTS.md, CLAUDE.md, GEMINI.md et les delphi-ai-skills) comme option du wizard, active par défaut dans tous les presets.
  • Menu "DMVCFramework" dans le Project Manager de Delphi 12 et 13 : nouveau controller REST, controller web avec vue, groupe de routes Minimal API, vue TemplatePro ; l'unit est enregistrée toute seule (AddController ou Map<Name>Routes) et les bodies sont liés à une classe modèle avec [MVCFromBody] ou MapPost<TModel> ; avec OpenAPI actif, le modèle apparaît dans Swagger UI.
  • Web application : interface générée plus complète (Bootstrap 5.3, thème clair et sombre), Minimal API WebApp avec les mêmes pages, nouveau sample samples/webapp_htmx_forms avec un tableau filtrable via HTMX et des formulaires validés côté serveur avec réponse 422.
  • ProblemDetails est un vrai body RFC 7807 (application/problem+json) ; le 422 de la Minimal API a un membre errors champ par champ ; un body JSON du mauvais type répond 400 au lieu de 500.
  • Les nouveautés sont approfondies dans le guide officiel de DelphiMVCFramework, deuxième édition, sur Leanpub.
  • Auteur : Daniele Teti, créateur de DelphiMVCFramework.

Questions fréquentes

Qu'y a-t-il de nouveau dans DelphiMVCFramework 3.5 après la RC6 ?
La RC7 (22 septembre 2026) a ajouté la méthode HTTP QUERY, une revue de sécurité avec quelques défauts changés, des limites sur le serveur WebSocket et des corrections pour HTTP.sys, SQL Server et Delphi 13.2. Sur master, après la RC7, sont arrivés OpenAPI 3 et Swagger UI dans le wizard, le menu DMVCFramework dans le Project Manager de Delphi 12 et 13, les fichiers pour les agents IA (AGENTS.md et les delphi-ai-skills), des pages web générées plus complètes, le sample webapp_htmx_forms et un ProblemDetails conforme à la RFC 7807.
Comment activer la documentation OpenAPI 3 dans un projet DelphiMVCFramework ?
Dans les nouveaux projets, il suffit de l'option "API documentation (OpenAPI 3)" du wizard, active par défaut dans les presets RESTful API, Minimal API RESTful, Full-Stack et Custom. Dans les projets existants à base de controllers, on passe ssvOpenAPI3 comme dernier paramètre de TMVCSwaggerMiddleware ou du filtre Swagger(...) ; dans la Minimal API, on utilise le filtre OpenAPI(...) de MVCFramework.OpenAPI3. Le projet généré ne publie /openapi.json et Swagger UI sur /swagger que si le fichier .env définit dmvc.openapi.enabled=true.
Dans quelles versions de Delphi trouve-t-on le menu DMVCFramework dans le Project Manager ?
Dans Delphi 12 Athens et Delphi 13 Florence. Le menu apparaît avec un clic droit sur un projet DelphiMVCFramework et ne montre que les entrées adaptées au type de projet : controllers REST et web dans les projets à base de controllers, groupe de routes dans les projets Minimal API, vues TemplatePro là où le dossier des vues existe.
Où ces nouveautés sont-elles expliquées en détail ?
Dans le guide officiel de DelphiMVCFramework, deuxième édition, disponible sur Leanpub. Le post montre les nouveautés en captures d'écran, le guide les traite chapitre par chapitre.

Comments