DelphiMVCFramework 3.2.2-nitrogen
Overview of DelphiMVCFramework 3.2.2-nitrogen
This version introduces new features in many different areas (swagger, server side view, MVCActiveRecord, renders etc.) so there isn't a single-big-feature to talk about. This version contains also a good number of bugfixes. It's not a critical updated, but this is the best version ever (at least, so far...) and is the suggested version for starting new projects. Enjoy!
What's new in DelphiMVCFramework-3.2.2-nitrogen
-
⚡New! Support for Delphi 11.x Alexandria
-
⚡New
TMVCRESTClient
implementation based on *Net components, the previous one was based on INDY Components (thanks to João Antônio Duarte). -
⚡New!
MVCJSONRPCAllowGET
attribute allows a remote JSON-RPC published object, or a specific method, to be called using GET HTTP Verb as well as POST HTTP Verb. POST is always available, GET is available only if explicitly allowed.IMVCJSONRPCExecutor
allows to specify which HTTP Verb to use when call the server JSON-RPC methods. The default verb can be injected in the constructor and eachExecuteRequest
/ExecuteNotification
allows to override od adhere to the instance default. -
⚡New! eLua server side view support added! The View engine requires Lua's dlls so it is not included in the main package but in a sampl project. Check
serversideviews_lua
sample. -
✅ Improved! Under some heavy load circumnstances the logger queue can get full. Now
TThreadSafeQueue
class uses a cubic function instead of a linear one to wait in case of very high concurrency. This allows a better resiliency in case of high load. -
✅ Improved internal architecture of custom type serializers in case of dynamic linked packages.
-
✅ Improved Swagger/OpenAPI support for System Controllers and improved support for param models.
-
⚡New
TMVCLRUCache
implementation. Very efficient implementation of LRU cache borrowed directly from DMSContainer -
⚡New
TMVCRedirectMiddleware
to handle HTTP redirections in a very simple and flexible way. -
⚡New!
TMVCActiveRecord
supports XML field type in PostgreSQL (in addition to JSON and JSONB). -
⚡New
OnContextCreate
andOnContextDetroyed
events forTMVCEngine
. -
⚡New! Added parameter
RootNode
inBodyFor
andBodyForListOf<T>
methods, just like theBodyAs*
methods. -
⚡New! Added
NullableTGUID
inMVCFramework.Nullables.pas
. -
⚡New
property CustomIntfObject: IInterface
inTWebContext
. This property can be used to inject custom services factory.procedure TMyWebModule.WebModuleCreate(Sender: TObject); begin FMVC := TMVCEngine.Create(Self, procedure(Config: TMVCConfig) begin //configuration code end); FMVC.AddController(TMyController); FMVC.OnWebContextCreate( procedure(const CTX: TWebContext) begin CTX.CustomIntfObject := TServicesFactory.Create; //implements an interface end); FMVC.OnWebContextDestroy( procedure(const CTX: TWebContext) begin //do nothing here end); end;
-
✅ Added parameter to set local timeStamp as UTC.
-
✅ Improved OpenAPI (Swagger) support.
-
✅ Improved Support for OpenAPI (Swagger) API Versioning (check
swagger_api_versioning_primer
sample) -
✅ Improved! The unit tests fully test PostgreSQL, FirebirdSQL and SQLite while testing MVCActiveRecord framework. The other engines are tested using
activerecord_showcase
sample project. -
✅ Improved! MVCActiveRecord doeas a better job to handle TDate/TTime/TDateTime types for SQLite (it is automatic because SQLite doesn't support date/time types).
-
✅ Improved! PostgreSQL, FirebirdSQL, Interbase and SQLite now support tablename and fields with spaces.
-
✅ Improved Nullable Types. Now it's possible to assign
nil
to a nullable type and to check its state using the new propertyIsNull
which is the negation of the already available propertyHasValue
. -
✅ Improved! Now
TMVCStaticFileMiddleware
is able to manage high-level criteria to show/hide/mask specific files in the documetn web root. Check Issue 548 and the updated samplesamples\middleware_staticfiles\
for more info. -
✅ Improved! In case of multiple MVCPath, Swagger consider only the first one (Thanks to V. Ferri and our sponsors)
-
⚡New! Mechanism to customize the JWT claims setup using the client request as suggested in issue495
-
⚡New! Added
TMVCActiveRecord.Merge<T>(CurrentListOfT, ChangesOfT)
to allow merge between two lists ofTMVCActiveRecord
descendants usingUnitOfWork
design pattern. Check the button "Merge" in demo "activerecord_showcase". -
⚡ New! Added default filtering for
TMVCActiveRecord descendants
(more info ASAP) -
⚡ New! Serialization and Deserialization for Pascal
set
(Thanks to rshuck for his suggestions) -
⚡ New! Added partitioning for
TMVCActiveRecord descendants
(more info ASAP) -
✅ Dramatically improved all "JSON-To-DataSet" operations (1 order of magnitude c.a.). Thanks to MPannier and David Moorhouse for their detailed analysis - More info here.
-
✅ Improved! After a big refactoring ("I love to delete code" -- cit. Daniele Teti), support a new SQLGenerator is just 2 (two) methods away! Just as example, this is the current version of
TMVCSQLGeneratorPostgreSQL
type TMVCSQLGeneratorPostgreSQL = class(TMVCSQLGenerator) protected function GetCompilerClass: TRQLCompilerClass; override; public function CreateInsertSQL( const TableName: string; const Map: TFieldsMap; const PKFieldName: string; const PKOptions: TMVCActiveRecordFieldOptions): string; override; function GetSequenceValueSQL(const PKFieldName: string; const SequenceName: string; const Step: Integer = 1): string; override; end;
-
⚡ New! Added new default parameter to
TMVCActiveRecord.RemoveDefaultConnection
andTMVCActiveRecord.RemoveConnection
to avoid exceptions in case of not initialized connection. -
⚡ New! Added the new
MVCOwned
attribute which allows to auto-create nested objects in the deserialization phase. This will not change the current behavior, you ned to explocitly define a property (or a field) asMVCOwned
to allows the serialization to create or destroy object for you. -
✅ Improved!
Context.Data
property is now created on-demand using a lazy loading approach (expect an overall speed improvement). -
✅ Added
LogException
function inMVCFramework.Logger.pas
to easily log exception in standard way. -
✅ Improved
MVCAREntitiesGenerator
project - now it can better handle border cases, field names which collide with Delphi keywords and a big number of tables. -
✅ Improved error handling for JSON-RPC APIs (Thanks to David Moorhouse). More info here.
-
✅ Improved parameter handling for enum and set in JSON-RPC APIs.
-
⚡ New! Added
ActiveRecordConnectionRegistry.AddDefaultConnection(const aConnetionDefName: String)
. The connection definition must be known by FireDAC. This method simplifies the most common scenario shown below.ActiveRecordConnectionRegistry.AddDefaultConnection('MyConDefName'); try //Use active record classes finally ActiveRecordConnectionRegistry.RemoveDefaultConnection; end;
-
⚡ New! Added
ToJSONObject
andToJSONArray
to theIMVCRESTResponse
. These methods automatically parse the response body and return aTJSONObject
or aTJSONArray
respectively. These methods work as a factory - the client code need to handle returned istances. Is the body is not compatible with the request (a.k.a. is not a JSONObject in case ofToJSONObject
, or is not a JSONArray in case ofToJSONArray
) an exception is raised. -
⚡ New! Added support for primary GUID (UUID) primary keys, attributes and serialization (More info at issue 552). Thanks to Marcelo Jaloto for its important collaboration.
-
⚡ New! Added
TMVCJWTBlackListMiddleware
to allow black-listing and (a sort of) logout for a JWT based authentication. This middleware must be registered after theTMVCJWTAuthenticationMiddleware
.This middleware provides 2 events named:
OnAcceptToken
(invoked when a request contains a token - need to returns true/false if the token is still accepted by the server or not) andOnNewJWTToBlackList
(invoked when a client ask to blacklist its current token). There is a new sample available which shows the funtionalities:samples\middleware_jwtblacklist
. -
⚡New!
MVCFromBody
attribute, useful to automatically inject the request body as actual object in the action paramaters. For instance in the following action the body request is automatically deserialized as an object of class TPerson.//interface [MVCHTTPMethod([httpPOST])] [MVCPath('/people')] procedure CreatePerson(const [MVCFromBody] Person: TPerson); //implementation procedure TRenderSampleController.CreatePerson(const Person: TPerson); begin //here you can directly use Person without call Context.Request.BodyAs<TPerson> //the Person object lifecycle is automatically handled by dmvcframework, so don't destroy //If the request body doesn't exist (or cannot be deserialized) an exception is raised. end;
MVCFromBody can be used also with "Collection Like" data structures.
//interface[MVCDoc('Creates new articles from a list and returns "201: Created"')] [MVCPath('/bulk')] [MVCHTTPMethod([httpPOST])] procedure CreateArticles(const [MVCFromBody] ArticleList: TObjectList<TArticle>); //implementation procedure TArticlesController.CreateArticles(const ArticleList: TObjectList<TArticle>); var lArticle: TArticle; begin for lArticle in ArticleList do begin GetArticlesService.Add(lArticle); end; Render(201, 'Articles Created'); end;
-
⚡New!
MVCFromQueryString
attribute, useful to automatically inject a query string paramater an action paramater. For instance in the following action the query string paramsfromDate
is automatically deserialized as aTDate
value and injected in the action.//interface [MVCHTTPMethod([httpGET])] [MVCPath('/invoices')] procedure GetInvoices(const [MVCFromQueryString('fromDate')] FromDate: TDate); //implementation procedure TRenderSampleController.GetInvoices(const FromDate: TDate); begin //here FromDate is a valid TDate value deserialized from the querystring paramater //named fromDate. //If the query string parameter doesn't exist (or cannot be deserialized) an exception is raised. end;
-
⚡New!
MVCFromHeader
attribute, useful to automatically inject a header value as an action parameter. For instance in the following action the header paramsXMyCoolHeader
is automatically deserialized asString
value and injected in the action.//interface [MVCHTTPMethod([httpGET])] [MVCPath('/invoices')] procedure GetInvoices(const [MVCFromQueryString('fromDate')] FromDate: TDate; const [MVCFromHeader('X-MY-COOL-HEADER')] XMyCoolHeader: String); //implementation procedure TRenderSampleController.GetInvoices(const FromDate: TDate; const XMyCoolHeader: String); begin //here XMyCoolHeader is a string read from the "X-MY-COOL-HEADER' request header. //If the header doesn't exist (or cannot be deserialized) an exception is raised. end;
-
⚡New!
MVCFromCookie
attribute, useful to automatically inject a cookie value as an action parameter. For instance in the following action the cookieMyCoolCookie
is automatically deserialized asTDate
value and injected in the action.//interface [MVCHTTPMethod([httpGET])] [MVCPath('/invoices')] procedure GetInvoices( const [MVCFromQueryString('fromDate')] FromDate: TDate; const [MVCFromHeader('X-MY-COOL-HEADER')] XMyCoolHeader: String; const [MVCFromCookie('MyCoolCookie')] MyCoolCookie: TDate; ); //implementation procedure TRenderSampleController.GetInvoices(const FromDate: TDate; const XMyCoolHeader: String; const MyCoolCookie: TDate); begin //here MyCoolCookie is a TDate read from "MyCoolCookie' cookie available in the request. //If the cookie doesn't exist (or cannot be deserialized) an exception is raised. end;
-
✅ Improved! While not strictly required nor defined, DMVCFramework supports sending body data for all HTTP VERBS - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
-
⚡ New! Automated support to avoid "mid-air collisions". New methods
SetETag
andCheckIfMatch
allows a better security without adding complexity to the controller code - checkavoid_mid_air_collisions_sample.dproj
sample and see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag#avoiding_mid-air_collisions for more info about mid-air collisions. -
✅ Improved! Ignored fields handling now is much better in renders method and in
ObjDict
as well. See issue 528.
Bug Fixes in 3.2.2-nitrogen
-
Fix #484 (thanks to João Antônio Duarte)
-
Fix #472 (thanks to João Antônio Duarte)
-
Fix #470 (thanks to João Antônio Duarte)
-
Fix #453 (thanks to João Antônio Duarte)
-
Fix #455 (thanks to João Antônio Duarte)
-
Fix #461
-
Fix #493 (thanks to DelphiMan68 for his initial analisys)
-
Fix #451
-
Fix #539
-
Fix #560 (thanks to David Moorhouse)
-
Fix #335 (thanks to João Antônio Duarte)
-
Fix #564
-
Fix #570 (Thanks Marcos Nielsen)
-
Fix #565
-
Merged PR#543 (Now the
PathInfo
is trimmed so the router convert this "http://myserver.com/one " to this "http://myserver.com/one") -
Fix for nil objects in lists during serialization
-
Fix a very subtle bug in
MaxRecordCount
parameter for RQL based methods inTMVCActiveRecord
-
Uniformed behavior in
Update
andDelete
method inTMVCActiveRecord
. Now these methods raise an exception if the record doesn't exists anymore in the table (update or delete statements returnAffectedRows
= 0). The behavior can be altered using the new parameter in the call, which by default istrue
.WARNING! This change could raise some incompatibilities with the previous version, however this is the correct behavior. Consider the previous one a "incorrect behavior to fix".
-
Fix #489
-
Fix #518 (Thanks to Microcom-Bjarne)
-
Fix #526 (Thanks to David Moorhouse)
-
Fix #544 (Thanks to David Moorhouse)
-
Fix #542 (Thanks to Lamberto Lodi for the hints)
-
Fix #485
-
Fixed fileupload sample
-
Fixed an
IFDEF
compatibility problem on mobile platforms (Thanks to Marco Cotroneo) -
Samples are syntax compatible with Delphi 10.1 Berlin or better (Thanks to Mark Lobanov)
Breaking Changes in 3.2.2-nitrogen
- Removed deprecated constructor for
TMVCJWTAuthenticationMiddleware
- was deprecated since 2019. Just use the other one as suggested. - Changed signature of method
IMVCMiddleware.OnAfterControllerAction