Become a member!

DelphiMVCFramework 3.5 RC7 entra en el Project Manager de Delphi y habla con los agentes de IA

🌐
Este artículo también está disponible en otros idiomas:
🇬🇧 English  •  🇮🇹 Italiano  •  🇩🇪 Deutsch  •  🇧🇷 Português  •  🇫🇷 Français

DelphiMVCFramework, el framework open source REST y web para Delphi

¿Qué ha cambiado en DelphiMVCFramework después de la RC6? El trabajo en la 3.5 se ha centrado en cómo creas un proyecto y lo haces crecer, dentro del IDE de Delphi y junto a los agentes de IA. Esta vez te lo enseño con capturas.

DelphiMVCFramework 3.5.0-silicon RC7 es una release candidate, no la 3.5.0 definitiva: las funcionalidades son las que ves aquí, y la etiqueta estable llegará después de que la RC se haya ejecutado en máquinas distintas de la mía.

La RC6 es del 23 de agosto, y el post que la anunciaba hablaba de hosts, Minimal API y serializador en streaming. La RC7 salió el 22 de septiembre. Después, en master, llegaron dos novedades para el trabajo de todos los días en un proyecto. Un menú DMVCFramework en el Project Manager de Delphi crea controladores, grupos de rutas y vistas y los registra en el proyecto. Los ficheros para los agentes de IA le dan a tu asistente las reglas y los fuentes del framework, para que no escriba la API de memoria. Luego está el resto: Swagger UI con OpenAPI 3, las páginas web generadas, QUERY, ProblemDetails.

Aquí abajo tienes un recorrido rápido, casi todo con imágenes. Cada tema tiene su capítulo en la guía oficial, segunda edición, con el código completo y las explicaciones que en este post me salto.


Qué está dónde

Todo lo que ves aquí pertenece a la RC7: es la versión que el asistente escribe en los proyectos generados (3.5.0-silicon-rc7, la ves también en las capturas). Pero una parte todavía no está en el zip de la etiqueta:

  • En la RC7 (etiqueta v3.5.0-silicon-rc7): el método HTTP QUERY, la revisión de seguridad con sus nuevos valores por defecto, los límites del servidor WebSocket, las correcciones para HTTP.sys, SQL Server y Delphi 13.2.
  • En master, después de la RC7: todo lo demás. El menú en el Project Manager, los ficheros para los agentes de IA, el asistente con OpenAPI 3, las páginas web generadas, el ejemplo con los formularios, ProblemDetails. Para tenerlos, clona master.

Las capturas de aquí abajo vienen de master.


Un menú DMVCFramework en el Project Manager

En Delphi 12 y 13, clic derecho sobre un proyecto DelphiMVCFramework en el Project Manager, y hay un submenú DMVCFramework:

El menú DMVCFramework en el Project Manager de Delphi 13, con la entrada New REST Controller

Eliges New REST Controller…, escribes el nombre, y el resto se rellena solo: el segmento de URL y la clase del modelo a la que se enlaza el body de las peticiones.

La ventana New REST controller con Name Orders, URL segment orders y Model class TOrder

Pulsas OK y el menú crea Controllers.OrdersU.pas, lo añade al proyecto y lo registra en EngineConfigU.pas: la unit en la uses y AEngine.AddController(TOrdersController) junto a los demás controladores. Los cambios pasan por el buffer del editor, así que un Ctrl+Z los deshace.

EngineConfigU.pas en el IDE después de añadir Controllers.OrdersU a la uses

Este es el controlador generado, tal como sale del menú en un proyecto que tiene la documentación OpenAPI activa:

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;
    ...

El body llega ya deserializado en Item y ya validado: sin name la petición ni siquiera entra en la action y el cliente recibe un 422. El esquema de las respuestas viene de la clase del modelo: con el último argumento de MVCSwagResponses el documento describe también el envoltorio {"data": ...} que añade OkResponse. Los atributos MVCSwag* solo aparecen si el proyecto publica un documento OpenAPI, y por eso Orders y su modelo aparecen en Swagger UI sin que yo haya escrito una línea: lo ves más abajo.

El menú muestra solo lo que el proyecto puede alojar. En un proyecto Minimal API el controlador no tendría sentido, y de hecho la entrada es otra:

El menú DMVCFramework en un proyecto Minimal API, con la entrada New Minimal API Route Group

New Minimal API Route Group… crea OrdersRoutesU.pas con un procedimiento MapOrdersRoutes (bodies enlazados por tipo con MapPost<TOrder> y MapPut<Integer, TOrder>) y añade la llamada al final de ConfigureRoutes. Las otras dos entradas son New Web Controller and View… y New TemplatePro View…, y aparecen solo si el proyecto tiene una carpeta de vistas. En las versiones de Delphi anteriores a la 12 el menú no está.


Un proyecto que nace con las skills adecuadas

Si escribes código con Claude Code, Codex, Cursor o Gemini, un agente que no conoce DelphiMVCFramework se inventa nombres de métodos plausibles, o usa los de una versión vieja, y el compilador te lo dice solo después.

Con la RC7 cada proyecto DelphiMVCFramework nuevo nace ya preparado para el agente: el asistente incluye las skills adecuadas para ese tipo de proyecto, tomadas de la misma línea del framework que estás usando. Son las buenas prácticas escritas para quien desarrolla con DelphiMVCFramework, divididas por tema:

  • Delphi: el lenguaje y la RTL, las diferencias entre versiones, la gestión de memoria, strings, generics, hilos; más una skill de code review sobre warnings, análisis estático y memory leaks.
  • DelphiMVCFramework: controladores, ActiveRecord, validación, inyección de dependencias, middleware, los tres hosts, .env.
  • Seguridad: las reglas para cada endpoint que recibe input del cliente.
  • Tests: tests de integración con DUnitX.
  • Minimal API, aplicaciones web, interfaz, JSON-RPC: cuando el proyecto las usa.
  • HTMX: la documentación oficial, organizada para el agente.

La ventaja la ves desde la primera petición. Sin skills y sin AGENTS.md, cada sesión con el agente empieza explicándole el proyecto y el framework, y sigue corrigiendo el código que ha escrito de memoria: un método que no existe, un patrón de una versión vieja, un objeto liberado dos veces. Con el proyecto generado por el asistente, el agente ya sabe cómo está hecho el proyecto, dónde están los fuentes del framework y cómo se escribe un controlador, una entidad ActiveRecord o una página HTMX en DelphiMVCFramework 3.5. Ese tiempo lo ahorras en cada sesión.

También está la seguridad. Entre las skills instaladas en cada proyecto está dmvcframework-security, con las reglas para cualquier endpoint que recibe input del cliente: control de acceso, mass assignment, SQL injection, XSS, CSRF, path traversal y uploads, JWT, secretos y mensajes de error, más una checklist que pasar antes de que un endpoint vaya a producción. El agente la lee antes de escribir un endpoint, así que el código que obtienes tiende a ser más seguro que el que escribiría partiendo de cero.

Las skills viven en un repositorio aparte, con una rama para cada línea del framework, y se actualizan con independencia de las releases: cuando sale una versión nueva de una skill, update_ai_skills.bat en la carpeta del proyecto la trae.

La opción está en la página Project Options, AI coding agent files and skills, y está activa por defecto en todos los presets. Las skills se descargan mientras el asistente crea el proyecto, con una barra de progreso que puedes cancelar; si no las necesitas, desmarca la casilla.

La página Project Options del asistente con la opción AI coding agent files and skills

Con la opción activa el asistente escribe en la carpeta del proyecto un AGENTS.md con los datos del proyecto, más CLAUDE.md y GEMINI.md, que lo importan. Luego descarga en .claude\skills las delphi-ai-skills adecuadas para ese tipo de proyecto, desde la rama que corresponde a la versión del framework (dmvc-3.5 para esta). Este es el AGENTS.md de un proyecto RESTful API generado por la suite de tests del asistente, que lo llama 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 -->

El último bloque le dice al agente dónde están, en tu disco, los fuentes del framework y de la RTL: cuando tiene una duda sobre un nombre va a leer el código real.

Qué skills se instalan depende del proyecto. delphi, delphi-code-smells, dmvcframework, dmvcframework-security y dmvcframework-testing están siempre; un proyecto Minimal API añade dmvcframework-minimal-api, una aplicación web dmvcframework-webapp y dmvcframework-ui, con HTMX también htmx-skill, un servicio JSON-RPC dmvcframework-jsonrpc. Si durante la creación la descarga falla, el proyecto se crea igual, con un warning, y update_ai_skills.bat completa la instalación en cuanto tengas conexión.


El asistente: documentación de la API y clave JWT

En la página Features del preset Custom hay una opción nueva, API documentation (OpenAPI 3). En los otros presets no la ves porque ya está decidida: está activa en RESTful API, Minimal API RESTful y Full-Stack.

La página Features del asistente de DelphiMVCFramework con la opción API documentation (OpenAPI 3)

Con la opción activa el asistente descarga la release oficial de Swagger UI (5.33.0, verificada con SHA-256) en bin\www\swagger mientras crea el proyecto. Si estás sin conexión el proyecto se crea igual y en esa carpeta encuentras un README con los pasos para descargarla a mano. El documento se publica solo si el .env contiene dmvc.openapi.enabled=true: el .env generado lo contiene, el de producción no, y en producción la documentación no sale.

Los proyectos con JWT ahora tienen en el .env una JWT_SECRET propia, 384 bits del generador criptográfico del sistema, distinta en cada generación. El .gitignore generado ya excluye el .env.


Swagger UI con OpenAPI 3

Este es el proyecto generado con el preset RESTful API, al que he añadido el controlador Orders con el menú que acabas de ver. Lo arrancas, abres http://localhost:8080/swagger y te encuentras esto:

Swagger UI mostrando el documento OpenAPI 3 de un proyecto DelphiMVCFramework basado en controladores

El middleware Swagger, el que usas desde hace años, ahora produce también OpenAPI 3. El documento lo construye SwagDoc, la librería incluida en el framework, y el soporte de OpenAPI 3 en SwagDoc lo escribió Marcelo Jaloto (PR #916): ¡gracias, Marcelo! El formato se elige con un nuevo último parámetro, ASpecVersion, que por defecto sigue siendo Swagger 2.0, así que quien actualiza no ve cambiar nada. El proyecto generado lo registra así:

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')));

Funciona todo lo que funcionaba con Swagger 2.0: seguridad JWT y basic, MVCSwagAuthentication, MVCSWAGDefaultModel, las rutas CRUD de TMVCActiveRecordController. El esquema JWT es http/bearer, así que en la ventana Authorize pegas el token tal cual. El servidor en el documento es relativo, y “Try it out” llama al origen que sirvió el documento, también detrás de un proxy.

La operación POST /api/orders en Swagger UI, con el body requerido y las respuestas 201 y 422

En los proyectos Minimal API el asistente registra en cambio el filtro OpenAPI(...) de MVCFramework.OpenAPI3, que genera un documento OpenAPI 3.1 a partir de las rutas lambda y lo publica en la misma URL, con la misma Swagger UI.

Los campos TDate, TDateTime y TTime ahora se describen con los formatos estándar date, date-time y time, así que un cliente regenerado desde el documento obtiene tipos fecha en lugar de strings (esto también llega con la PR de Marcelo). Los atributos de documentación de los campos ahora se llaman todos MVCSwag*: MVCFormat, MVCMinimum y MVCMaximum todavía compilan, con un warning, hasta la 4.0.


Las aplicaciones web generadas

El preset Web Application ahora parte de una interfaz más completa: cabecera de página, un panel con el estado del servidor actualizado vía HTMX, una lista “Start here” con los primeros pasos, tema claro y oscuro. Pero el código generado sigue siendo el mínimo: el ejemplo con tabla y formularios ha pasado a un ejemplo aparte, del que hablo más abajo.

La página de inicio de una aplicación web DelphiMVCFramework generada por el asistente, tema oscuro

La misma página de inicio con el tema claro

El preset Minimal API WebApp genera las mismas páginas, con las rutas lambda en lugar de los controladores. Aquí abajo está la página de login después de un intento fallido: el nombre de usuario se queda en el campo, la contraseña no. El formulario está enlazado a una clase, y la página lo vuelve a mostrar desde ahí.

La página de login de una Minimal API WebApp después de credenciales incorrectas


Tablas y formularios con HTMX: webapp_htmx_forms

El ejemplo de la tabla People, que antes estaba en el proyecto generado, se ha convertido en un ejemplo propio: samples/webapp_htmx_forms. Ahí están la búsqueda, los filtros, la ordenación y los formularios completos, sin hacer más pesado cada proyecto nuevo.

La tabla se filtra, se busca y se ordena por columna. Con HTMX el servidor devuelve solo el fragmento de la tabla y la página no se recarga; la action decide si manda la página entera o el fragmento, y pone Vary: HX-Request porque la misma URL tiene dos bodies distintos.

La tabla People del ejemplo webapp_htmx_forms filtrada con la búsqueda analyst

Los formularios de alta y edición usan todas las macros de la librería de formularios de TemplatePro (bin/templates/lib/forms_bootstrap5.tpro, que el asistente copia en cada proyecto TemplatePro) y se validan en el servidor con los atributos de DelphiMVCFramework y TMVCValidationEngine. Si algo falla, el formulario vuelve con estado 422, los valores que escribiste y el mensaje junto al campo. Si todo va bien, redirección a la tabla (Post/Redirect/Get), así un F5 no reenvía el formulario.

El formulario New person mostrado de nuevo con errores de validación en Name y Joined

En el lado de TemplatePro, la caché de las vistas compiladas ahora vive en memoria: con view_cache=true, después de la primera petición una vista ya no toca el disco. Si las modificas con el servidor en marcha, dmvc.view_cache_check_changes=true reactiva la comprobación en cada petición, layouts y partials incluidos.


Formularios generados con TemplatePro

El formulario de la captura de arriba viene de la librería de formularios de TemplatePro, forms_bootstrap5.tpro, que el asistente copia en bin/templates/lib en cada proyecto con vistas TemplatePro. La importas una vez al principio de la página y tienes ocho macros: form, input, textarea, select, checkbox, submit, actions y 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}}

Cada macro lee el valor del campo de formModel y el mensaje de error de formErrors, dos variables que asignas en la action. El modelo puede ser un objeto, el registro actual de un dataset, un objeto JSON o un diccionario. Si hay un error para ese campo, el control toma la clase is-invalid y el mensaje aparece debajo: es lo que ves en el formulario devuelto con el 422. Valores y mensajes siempre van con escape HTML, las fechas se formatean para los controles date, time y datetime-local, y con attrs pasas un mapa de atributos extra, por ejemplo los de HTMX. La misma página sirve para crear y para editar: solo cambian el modelo y la action.

Luego está auto, que genera por sí sola todo el formulario:

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

Un formulario generado por f.auto a partir de las propiedades de un objeto Delphi

auto recorre los campos del modelo (model.@@fields: las propiedades de un objeto o los campos de un dataset) y elige el control según el tipo. Un string se convierte en un campo de texto con maxlength tomado del tamaño, un entero en un campo numérico, un TDate en un date picker, un TDateTime en un datetime-local, un TTime en un campo de hora, un Boolean en una checkbox, un memo en una textarea. Una propiedad sin setter se vuelve readonly. La etiqueta viene del nombre: FullName se convierte en “Full name”. Con exclude quitas los campos que no quieres mostrar.

Si el modelo es una entidad TMVCActiveRecord, añade a la uses la unit MVCFramework.View.Renderers.TemplatePro.ActiveRecord (el asistente lo hace solo en los proyectos con ActiveRecord y TemplatePro). A partir de ahí los campos siguen el mapeo de ActiveRecord y los validadores: [MVCRequired] se convierte en el atributo required, [MVCMaxLength(n)] en maxlength. Para todo lo demás está TTProConfiguration.OnGetFieldMetadata, que te deja cambiar etiqueta, tipo, visibilidad y obligatoriedad de cada campo. El formulario completo con todas las macros lo encuentras en la página /forms del ejemplo samples/wizard_showcase/web.


ProblemDetails más fiel a la RFC 7807

Las respuestas de ProblemDetails(...) ahora siguen más de cerca la RFC 7807: el problem object es el body entero y el Content-Type es application/problem+json. El 422 de la Minimal API tiene además un miembro errors, con el mensaje de cada campo.

Este es el grupo de rutas Orders generado por el menú, en un proyecto Minimal API: un POST sin name, luego un POST con un array en lugar del objeto.

$ 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 array donde hace falta un objeto es un error del cliente, así que la respuesta es un 400, tanto en los controladores con [MVCFromBody] como en la Minimal API.


El método HTTP QUERY

QUERY (RFC 10008) es seguro e idempotente como GET, pero tiene body: la búsqueda viaja en el payload y no en la URL, así que no tiene límites de longitud y no acaba en los logs de acceso, en las cachés de los proxies ni en el historial del navegador. Hablé de él en detalle en un post dedicado. En la RC7 lo tienes en los controladores, en la Minimal API (MapQuery) y en IMVCRESTClient (Query).

El ejemplo samples/routing hace la misma búsqueda dos veces, con GET y con 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}]

Antes de ponerlo en producción: para el CSRF trátalo como POST, no como GET. El valor por defecto de Access-Control-Allow-Methods del filtro CORS no lo incluye, y si un navegador de otro origen tiene que llamarlo debes pasar la lista completa. Y en el documento Swagger/OpenAPI no aparece: el slot query existe solo en OpenAPI 3.2, y el framework omite el verbo en lugar de escribir un documento no válido.


Seguridad: valores por defecto más seguros

La RC7 contiene una revisión de seguridad de la rama 3.5, y algunos valores por defecto ahora son más seguros. Si actualizas desde una versión anterior, estos son los que tienes que conocer:

  • X-HTTP-Method-Override ya no está soportado. Reescribir el verbo de una petición le toca al reverse proxy o al servidor web que está delante de la aplicación.
  • IMVCRESTClient y TMVCSSEClient aceptan solo certificados válidos. Para un test contra un host con certificado self-signed está MVCRESTClientAcceptInvalidCertificates := True.
  • La cookie de sesión es HttpOnly por defecto, y desde Delphi 11 tiene SameSite=Lax. Secure es un parámetro nuevo, apagado por defecto porque encenderlo rompería cualquier entorno de desarrollo en HTTP; los proyectos generados lo leen de SESSION_COOKIE_SECURE en el .env.
  • Por encima de max_request_size la respuesta es 413 en todos los hosts, con el mismo comportamiento en Indy, HTTP.sys y WebBroker.
  • Más protección contra los JSON maliciosos: el parser rechaza los documentos construidos para poner en apuros al servidor.
  • [MVCMaxLength(n)] y [MVCPattern(...)] validan siempre, en cualquier orden en que aparezcan las units en la uses. Esto está en master: si tienes modelos con esos atributos, después de actualizar los encuentras validados.

La lista completa, con el motivo de cada cambio, está en la sección Security del changelog.


El resto, en breve

  • Rutas comprobadas al registrarlas. Los tipos de los parámetros (int, int64, float, bool, guid, date, time, datetime, sqids) vienen de una sola función para los controladores y para la Minimal API; time y datetime aceptan solo ISO 8601 y se enlazan a parámetros TTime y TDateTime. Un tipo desconocido, un parámetro sin nombre o un catch-all fuera de sitio hacen fallar el registro: el servidor no arranca, en lugar de responder 404 para siempre a una ruta mal escrita.
  • El body se puede devolver en la respuesta. Result := OkResponse(Person) con [MVCFromBody] Person, u Ok(Item) en la Minimal API: la respuesta se hace cargo del objeto y lo libera después del render.
  • HTTP.sys responde a PATCH, SEARCH y a los demás verbos que el kernel no interpreta por sí solo.
  • Servidor WebSocket: cuatro límites configurables sobre el handshake y el tamaño de los frames, activos por defecto (PR #915).
  • SQL Server: foRefresh devuelve la fila después de los triggers, Insert y Update funcionan en tablas con triggers, el bloqueo optimista se detecta también detrás de un trigger sin SET NOCOUNT ON (diagnóstico de Flavio Basile).
  • Delphi 13.2: el framework compila también con la última actualización de Delphi 13 (#917).
  • TemplatePro acepta más tipos de campo de los datasets y ya no muestra como negativos los valores unsigned grandes (contribución de Patrick Premartin).

En Patreon: artículos y vídeos sobre estas funcionalidades

Para los supporters en Patreon llegarán artículos y vídeos dedicados justo a estas novedades: el menú del Project Manager, las skills para los agentes de IA, la documentación OpenAPI generada. Cómo usarlas en el trabajo de todos los días, paso a paso.

Si usas DelphiMVCFramework a nivel profesional, te pido que apoyes el proyecto. Es una inversión en tu negocio: el framework sobre el que trabajas sigue creciendo, y como supporter puedes orientar sus próximos desarrollos. Además tienes acceso a los contenidos formativos dedicados, a los grupos de Discord reservados con soporte preferente y al soporte prioritario por email.


Probarla

Para la RC7, descarga el zip desde la página de release y añade sources al library path. Para todo lo demás clona master e instala el package dmvcframeworkDT de tu versión de Delphi: los presets aparecen en File > New > Other, bajo Delphi > DelphiMVCFramework, y el menú en el Project Manager llega con el mismo package.

Si algo no cuadra, abre un issue en GitHub. Todavía estamos en fase de release candidate, y es ahora cuando un informe de error se convierte en una corrección en la 3.5.0.


Recursos

PATREON Community

Enjoy!

– Daniele Teti

Datos clave
  • Tema: las novedades de DelphiMVCFramework 3.5.0-silicon después de la RC6 (23 de agosto de 2026): la RC7 (etiqueta v3.5.0-silicon-rc7, 22 de septiembre de 2026) y lo que está en master a 5 de octubre de 2026 (misma versión, 3.5.0-silicon-rc7). Es una release candidate, no la 3.5.0 definitiva.
  • En la RC7: método HTTP QUERY (RFC 10008) con [MVCHTTPMethod([httpQUERY])], MapQuery en la Minimal API y Query en IMVCRESTClient; HTTP.sys deja de tratar SEARCH y otros verbos como GET; una revisión de seguridad con nuevos valores por defecto (sesión HttpOnly, 413 en todos los hosts por encima de max_request_size, protección contra JSON maliciosos, X-HTTP-Method-Override ignorado, certificados no válidos rechazados por IMVCRESTClient); límites en el servidor WebSocket; correcciones para SQL Server y para Delphi 13.2.
  • En master después de la RC7: OpenAPI 3 desde el middleware Swagger (ssvOpenAPI3), opción "API documentation (OpenAPI 3)" en el asistente con Swagger UI 5.33.0 descargada al crear el proyecto y publicada en /swagger cuando el .env pone dmvc.openapi.enabled=true; clave JWT generada en el .env; ficheros para agentes de IA (AGENTS.md, CLAUDE.md, GEMINI.md y las delphi-ai-skills) como opción del asistente, activa por defecto en todos los presets.
  • Menú "DMVCFramework" en el Project Manager de Delphi 12 y 13: nuevo controlador REST, controlador web con vista, grupo de rutas Minimal API, vista TemplatePro; la unit se registra sola (AddController o Map<Name>Routes) y los bodies se enlazan a una clase modelo con [MVCFromBody] o MapPost<TModel>; con OpenAPI activo el modelo aparece en Swagger UI.
  • Aplicaciones web: interfaz generada más completa (Bootstrap 5.3, tema claro y oscuro), Minimal API WebApp con las mismas páginas, nuevo ejemplo samples/webapp_htmx_forms con tabla filtrable vía HTMX y formularios validados en el servidor con respuesta 422.
  • ProblemDetails es un body RFC 7807 de verdad (application/problem+json); el 422 de la Minimal API tiene un miembro errors campo por campo; un body JSON del tipo equivocado responde 400 en lugar de 500.
  • Las novedades se explican en detalle en la guía oficial de DelphiMVCFramework, segunda edición, en Leanpub.
  • Autor: Daniele Teti, creador de DelphiMVCFramework.

Preguntas frecuentes

¿Qué hay de nuevo en DelphiMVCFramework 3.5 después de la RC6?
La RC7 (22 de septiembre de 2026) añadió el método HTTP QUERY, una revisión de seguridad con algunos valores por defecto cambiados, límites en el servidor WebSocket y correcciones para HTTP.sys, SQL Server y Delphi 13.2. En master, después de la RC7, llegaron OpenAPI 3 y Swagger UI en el asistente, el menú DMVCFramework en el Project Manager de Delphi 12 y 13, los archivos para los agentes de IA (AGENTS.md y las delphi-ai-skills), páginas web generadas más completas, el ejemplo webapp_htmx_forms y ProblemDetails conforme a RFC 7807.
¿Cómo se activa la documentación OpenAPI 3 en un proyecto DelphiMVCFramework?
En los proyectos nuevos basta la opción "API documentation (OpenAPI 3)" del asistente, activa por defecto en los presets RESTful API, Minimal API RESTful, Full-Stack y Custom. En los proyectos existentes basados en controladores se pasa ssvOpenAPI3 como último parámetro de TMVCSwaggerMiddleware o del filtro Swagger(...); en la Minimal API se usa el filtro OpenAPI(...) de MVCFramework.OpenAPI3. El proyecto generado publica /openapi.json y Swagger UI en /swagger solo si el fichero .env pone dmvc.openapi.enabled=true.
¿En qué versiones de Delphi está el menú DMVCFramework en el Project Manager?
En Delphi 12 Athens y Delphi 13 Florence. El menú aparece con un clic derecho sobre un proyecto DelphiMVCFramework y muestra solo las entradas adecuadas al tipo de proyecto: controladores REST y web en los proyectos basados en controladores, grupo de rutas en los proyectos Minimal API, vistas TemplatePro donde existe la carpeta de vistas.
¿Dónde se explican en detalle estas novedades?
En la guía oficial de DelphiMVCFramework, segunda edición, disponible en Leanpub. El post enseña las novedades con capturas, la guía las trata capítulo a capítulo.

Comments