DelphiMVCFramework
? Help DMVCFramework and your business! Click Here to access premium contents!
Code Contributors
Contributing
We welcome contributions! If you\’d like to contribute to the DelphiMVCFramework, fork the project, create your test, add your changes and create a PR.
Table of Contents
- What\’s DelphiMVCFramework
- Support DMVCFramework
- DelphiMVCFramework Main Features
- Install the latest stable version
- Book: \”DelphiMVCFramework – the official guide\”
- Book translations
- How to partecipate to DMVCFramework development and/or tests
- Sponsors
- What users say about DMVCFramework
- What\’s New in DMVCFramework-3.4.2-magnesium (stable version)
- Older Versions
- What\’s New in DMVCFramework-3.4.1-sodium
- What\’s New in DMVCFramework-3.4.0-neon
- What\’s New in DMVCFramework-3.3.0-fluorine
- What\’s New in DMVCFramework-3.2.3-radium
- Bug Fix in 3.2.3-radium
- What\’s new in DMVCFramework-3.2.2-nitrogen
- Bug Fixes in 3.2.2-nitrogen
- Breaking Changes in 3.2.2-nitrogen
- What\’s New in DelphiMVCFramework 3.2.1-carbon
- Improvements
- What\’s New in 3.2.0-boron
- Breaking Changes in 3.2.0-boron
- Bug Fixes in 3.2.0-boron
- What\’s New in 3.1.0-lithium
- What\’s New in 3.0.0-hydrogen
- What\’s New in 2.1.3-lithium
- What\’s New in 2.1.2-helium
- What\’s New in 2.1.1-hydrogen
- Roadmap
- Trainings, consultancy or custom development service
- Samples and documentation
- Getting Started: 5 minutes guide
- DelphiMVCFramework Installation
- Sample Controller
- How to create a dmvcframework servers container
- RQL Introduction
- RQL as Implemented by DMVCFramework
- dotEnv syntax
- Links
What\’s DelphiMVCFramework
DMVCFramework is the most popular Open Source Delphi framework on Github which provides an easy to use, scalable, flexible RESTful, JSON-RPC and ActiveRecord framework for Delphi developers. DMVCFramework is the most popular Delphi project on GitHub and compiles for Windows (32 and 64bit) and Linux (64bit). DMVCFramework services can be compiled as console application, Windows Service, Linux daemon, Apache module (Windows and Linux) and IIS ISAPI (Windows).
DMVCFramework works with Delphi 12 Athens, Delphi 11 Alexandria, Delphi 10.4 Sydney, Delphi 10.3 Rio, Delphi 10.2 Tokyo, Delphi 10.1 Berlin and Delphi 10 Seattle.
Support DMVCFramework
Are you using DMVCFramework? Do you want to say \”Thanks\”? Become a Patron!
DelphiMVCFramework Main Features
-
DMVCFramwork is simple to use, has a lot of examples, is documented and there are a lot of tutorials available.
-
DMVCFramework is very well documented and the book DMVCFramework – the official guide is available to fastly get a solid knowledge (available as e-book and hardcopy).
-
There are more than 40 samples to learn all the features and be proficient and productive
-
Commercially supported by bit Time Professionals (training, consultancy, custom development etc.)
-
RESTful (RMM Level 3) compliant
-
JSON-RPC 2.0 Support with automatic objects remotization (check sample)
-
DMVCFramework\’ MVCActiveRecord allows an easy and fast database access.
-
Stable and solid, used by small/mid/big projects since 2010
-
Very fast!
-
Support group at https://www.*face*bo*ok.com/groups/delphimvcframework with more than 6000 active members
-
Can be used in load balanced environment
-
Wizard for the Delphi IDE. It makes DelphiMVCFramework even more simple to use!
-
Optional server side session support
-
JSON Web Token Support (JWT) (check sample)
-
Extendable using middleware – simple hooks to handle request/response (check sample)
-
Flexible yet simple to use, authorization/authentication framework based on industry standards.
- HTTP Basic Authentication
- JWT Authentication
- Custom Authentication
- CORS support
-
Controllers inheritance! You can define your own base controller and inherit from it.
-
Fancy URL with parameter mappings
-
Specialized renders to generate text, HTML, JSON.
-
Powerful and customizable mapper to serialize/deserialize data.
-
Can be packaged as stand alone server, apache module (XE6 or better) and ISAPI dll
-
Integrated REST Client
-
Works on Linux (Delphi 10.2 Tokyo or better)
-
Completely unit tested (more than 250 unit tests)
-
There is a sample for each functionality (check the dmvcframework_(yourversion)_samples.zip)
-
Server side generated pages using Mustache for Delphi or TemplatePro
-
Specific trainings are available (email to
professionals@bittime.itfor a date and a place) -
Push notifications support using ServerSentEvents
-
Automatic documentation through
/system/describeserver.info -
Driven by its huge community (Facebook group https://www.*face*bo*ok.com/groups/delphimvcframework)
-
Semantic Versioning
-
To get a fast introduction to DMVCFramework read the slides from ITDevCon conference
Install the latest stable version
If you are not involved in development or testing, do not clone the repo! Use the Github release!
The last stable version available here ?. Just download latest release as a zip file and you are ok. Samples are available as separate zip file downloadable from the same page where you download the release.
Book: \”DelphiMVCFramework – the official guide\”
The official guide for DMVCFramework is available. DMVCFramework has a lot functionalities and can really help your business. However many developers don\’t use it at its full potential. Why don\’t get more when is easily available? The DMVCFramework lead developer and project coordinator Daniele Teti, wrote the official guide for this great framework.
Buy your copy and improve your DMVCFramework knowledge now!
\”DMVCFramework – the official guide\” is available as e-book and hardcopy, pick what you prefer.
While a huge work has been done by the author and the reviews to make the book and the examples well written, complete and effective, things can be always improved. For any suggestions, complains or requests there is the official Github book project (https://*g*ithub.*com/danieleteti/dmvcframeworktheofficialguide) where you can fill an issue and get in touch directly with the author.
Book translations
Given the success of DMVCFramework in the Delphi community, the official DMVCFramework guide has been translated also in the following languages.
- Brazilian Portuguese (Translated by Diego Farisato)
- Spanish (Translated by Josè Davalos)
Please, if you use DMVCFramework \”star\” this project in GitHub! It cost nothing to you but helps other developers to reference the code.
How to partecipate to DMVCFramework development and/or tests
Only if you want to participate to the testing phase (which usually contains brand new features but can sometimes be instable) you can get the development version clonig this repo or downloading the master repository zip file.
Take in mind that even if development version is usually very stable, it isn\’t not ready for production utilization.
Sponsors
While DMVCFramework is born from the head of Daniele Teti from bit Time Professionals, it wouldn\’t what is now without the support and work of many people all around the world. The following companies sponsored some specific part of DMVCFramework so they wort a special mention.
GOLD SPONSORS
| COMPANY NAME | LOGO |
|---|---|
| bit Time Professionals | |
| bit Time Professionals – ITALY | |
| bit Time Software |
SILVER SPONSOR
| COMPANY NAME | LOGO |
|---|---|
| Centro Software | |
| Delphi Studio ES | |
| Orion Law | |
| Vivaticket |
What users say about DMVCFramework
\”Our wishes are coming true\” — one Delphi programmer after a small dmvcframework demo for an IT department of a very important national research institute
\”I\’m still amazed by the DelphiMVCFramework code and documentation. Thank you very much and I am amazed by your quick feedback.\” — Benjamin Yang (Director of SQLGate)
\”DMVCFramework and the Entity utility are fantastic!\” — Roberto
\”DMVCFramework is a great framework. It\’s very intuitive, fast, easy to use, actually there is nothing more to ask for.\” — Samir
\”Wow! To do that in J2EE it takes 2 days\” — a training participant after a 5 minutes demo.
\”I\’m starting with the DMVCFramework and I\’m finding it fantastic, congratulations for the project!\” — Rafael
\”I\’m looking at DMVCFramework project in it works great – for my use case scenarios is much better than \’Similar commercial product\’.\” — Luka
\”It\’s fantastic! Just define your entities and you are up and running in 5 minutes. Nothing comparable on the market.\” — Marco
\”The best framework for creating web servers with Delphi! It is very easy to create Delphi servers and publish APIs and Rest resources.
Congratulations to Daniele Teti and all the staff for the excellent work!\” — Marcos N.
We started the process of migrating our systems to micro services and are loving the DMVCFramework \”DMVCFramework is definitely part of our lives right now\”. — E. Costa
\”Thank you for the great framework! We are very happy with this!\” — Andreas
\”I managed to generate an API for my application thanks to this framework, it is truly useful and efficient!\” — J. Urbani
What\’s New in DMVCFramework-3.4.2-magnesium (stable version)
A deep analisys of what\’s new in DelphiMVCFramework-3.4.2-magnesium is available on [Daniele Teti Blog]
https://www.d*an*iel*eteti.it/post/delphimvcframework-3-4-2-magnesium/
Older Versions
What\’s New in DMVCFramework-3.4.1-sodium
A deep analisys of what\’s new in DelphiMVCFramework-3.4.1-sodium is available on Daniele Teti Blog ?
What\’s New in DMVCFramework-3.4.0-neon
Deeper analisys of what\’s new in DelphiMVCFramework-3.4.0-neon is available on Daniele Teti Blog ?
-
⚡ Added support for dotEnv
-
⚡ Added MSHeap memory manager for Win32 and Win64 (https://gi**thub.co*m/RDP1974/DelphiMSHeap)
-
? FIX Issue 664 Thanks to MPannier
-
? FIX Issue 667
-
? FIX Issue 680
-
? FIX Issue 682 (Thanks to wuhao13)
-
? FIX Wrong comparison in checks for ro/RW/PK fields in
TMVCActiveRecord -
? FIX wrong default initialization for JWT (thanks to Flavio Basile)
-
⚡ Wizard updated to be dotEnv aware
-
⚡ Added HTMX server side support through unit
samples\\htmx\\MVCFramework.HTMX.pasand the relative sample (Thanks to David Moorhouse). This unit provides class helper forTMVCWebRequestandTMVCWebResponseclasses to easily work with HTMX. If you want to use this unit just download the samples and add it to your project or put$(DMVCHOME)\\samples\\htmxin your library path. -
⚡ Added \”Load Style\” methods to
TMVCActiveRecord(more info #675)-
TMVCActiveRecordsupport \”Factory Style\” and \”Load Style\” methods when loads data from database.Using \”Factory Style\” methods (available from the first version) the result list is returned by the loader method (as shown in this piece of code from the
activerecord_showcasesample).Log(\'>> RQL Query (2) - \' + cRQL2); lCustList := TMVCActiveRecord.SelectRQL<TCustomer>(cRQL2, 20); try Log(lCustList.Count.ToString + \' record/s found\'); for lCustomer in lCustList do begin Log(Format(\'%5s - %s (%s)\', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault, lCustomer.City])); end; finally lCustList.Free; end;
For some scenarios would be useful to have also \”Load Style\” methods where the list is filled by the loader method (not instantiated internally).
Log(\'>> RQL Query (2) - \' + cRQL2); lCustList := TObjectList<TCustomer>.Create; try lRecCount := TMVCActiveRecord.SelectRQL<TCustomer>(cRQL2, 20, lCustList); //new in 3.4.0-neon Log(lRecCount.ToString + \' record/s found\'); for lCustomer in lCustList do begin Log(Format(\'%5s - %s (%s)\', [lCustomer.Code.ValueOrDefault, lCustomer.CompanyName.ValueOrDefault, lCustomer.City])); end; finally lCustList.Free; end;
-
-
⚡ Better error message in case of serialization of
TArray<TObject> -
⚡ Improved CORS handling – Issue 679 (Thanks to David Moorhouse)
-
⚡ Improved serialization of
TObjectList<TDataSet>(howeverObjectDictis still the preferred way to serialize multiple datasets). -
⚡ Added static method for easier cloning of FireDAC dataset into
TFDMemTable. -
In the class
EMVCExceptionthe propertyHTTPErrorCodehas been renamed inHTTPStatusCode. -
⚡ Functional Actions
-
In addition to the classic
procedurebased actions, now it\’s possibile to use functions as actions. TheResultvariable is automatically rendered and, if it is an object, its memory is freed.type [MVCNameCase(ncCamelCase)] TPersonRec = record FirstName, LastName: String; Age: Integer; class function Create: TPersonRec; static; end; [MVCNameCase(ncCamelCase)] TPerson = class private fAge: Integer; fFirstName, fLastName: String; public property FirstName: String read fFirstName write fFirstName; property LastName: String read fLastName write fLastName; property Age: Integer read fAge write fAge; end; [MVCPath(\'/api\')] TMyController = class(TMVCController) public { actions returning a simple type } [MVCPath(\'/sumsasinteger/($A)/($B)\')] function GetSum(const A, B: Integer): Integer; [MVCPath(\'/sumsasfloat/($A)/($B)\')] function GetSumAsFloat(const A, B: Extended): Extended; { actions returning records } [MVCPath(\'/records/single\')] function GetSingleRecord: TPersonRec; [MVCPath(\'/records/multiple\')] function GetMultipleRecords: TArray<TPersonRec>; { actions returning objects } [MVCPath(\'/objects/single\')] function GetSingleObject: TPerson; [MVCPath(\'/objects/multiple\')] function GetMultipleObjects: TObjectList<TPerson>; { actions returning datasets } [MVCPath(\'/datasets/single\')] function GetSingleDataSet: TDataSet; [MVCPath(\'/datasets/multiple\')] function GetMultipleDataSet: TEnumerable<TDataSet>; [MVCPath(\'/datasets/multiple2\')] function GetMultipleDataSet2: IMVCObjectDictionary; { customize response headers } [MVCPath(\'/headers\')] function GetWithCustomHeaders: TObjectList<TPerson>; end;
Check sample \”function_actions_showcase.dproj\” for more info.
-
-
⚡ Improved
TMVCResponsetype to better suits the new functional actions.TMVCResponsecan be used with \”message based\” responses and also with \”data based\” responses (with single object, with a list of objects or with a dictionary of objects).More info here
-
Removed
statuscode,reasonstringand all the field with a default value from exception\’s JSON rendering. All the high-level rendering methods will emit standardReasonString.Before
{ \"apperrorcode\": 0, \"statuscode\": 404, \"reasonstring\": \"Not Found\" \"classname\": \"EMVCException\", \"data\": null, \"detailedmessage\": \"\", \"items\": [], \"message\": \"[EMVCException] Not Found\" }Now
{ \"classname\": \"EMVCException\", \"message\": \"Not Found\" } -
⚡ New! SQL and RQL Named Queries support for TMVCActiveRecord.
Here\’s all the new methods available for Named Queries
class function SelectByNamedQuery<T: TMVCActiveRecord, constructor>( const QueryName: String; const Params: array of Variant; const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload; class function SelectByNamedQuery( const MVCActiveRecordClass: TMVCActiveRecordClass; const QueryName: String; const Params: array of Variant; const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = []): TMVCActiveRecordList; overload; class function SelectRQLByNamedQuery<T: constructor, TMVCActiveRecord>( const QueryName: String; const Params: array of const; const MaxRecordCount: Integer): TObjectList<T>; overload; class function SelectRQLByNamedQuery( const MVCActiveRecordClass: TMVCActiveRecordClass; const QueryName: String; const Params: array of const; const MaxRecordCount: Integer): TMVCActiveRecordList; overload; class function DeleteRQLByNamedQuery<T: TMVCActiveRecord, constructor>( const QueryName: String; const Params: array of const): Int64; class function CountRQLByNamedQuery<T: TMVCActiveRecord, constructor>( const QueryName: string; const Params: array of const): Int64;
MVCNamedSQLQueryallows to define a \”named query\” which is, well, a SQL query with a name. Then such query can be used by the methodSelectByNamedQuery<T>orSelectByNamedQuery. Moreover in the attribute it is possible to define on which backend engine that query is usable. In this way you can define optimized query for each supported DMBS you need.More info here
What\’s New in DMVCFramework-3.3.0-fluorine
- ⚡ Support for Delphi 11.3 Alexandria
- ⚡ Ability to use records in swagger param and response attributes Issue 649
- ⚡ Improved Wizard – now it produces commented code to show how to use
ContextEvents - ⚡ Improved compatibility with Delphi 10.2 Tokyo and older versions (Thanks Mark Lobanov)
- ⚡ Added sample and middleware for Prometheus (using https://gith**ub.com*/marcobreveglieri/prometheus-client-delphi)
- ⚡ Added \”Profiler.LogsOnlyIfOverThreshold\” which logs only if over the defined threshold
- ? FIX Issue 648 Thanks to sf-spb
- ? FIX Issue 652 Thanks to BssdTS
- ? PR 651 Thanks to Francisco Zanini
What\’s New in DMVCFramework-3.2.3-radium
-
⚡ Default error responses contains the official \”reason string\” associated to the HTTP status code (this can be a breaking change for some generic client which doesn\’t correctly interpret the http status code)
-
⚡ Added static method
HTTP_STATUS.ReasonStringFor(HTTPStatusCode)wich returns the standardReasonStringfor a given HTTP status code. -
⚡ Improved handling of
TMVCErrorResponseinformation -
⚡ mid-air-collision handling now uses SHA1 instead of MD5
-
⚡ Added
MVCFramework.Commons.MVC_HTTP_STATUS_CODESconst array containing all the HTTP status codes with itsReasonString. -
⚡ Support for
TObjectdescendants in JSONRPC APIs (not only for JSONObject and JSONArray). -
⚡ New global configuration variable
MVCSerializeNulls.- When MVCSerializeNulls = True (default) empty nullables and nil are serialized as json null.
- When MVCSerializeNulls = False empty nullables and nil are not serialized at all.
-
⚡ Nullable types now have
Equalmethod support, the new methodTryHasValue(out Value)works likeHasValuebut returns the contained value if present. Also there is a better \”equality check\” strategy. -
⚡ Unit tests now are always executed for Win32 and Win64 bit (both client and server).
-
⚡ Added
TMVCActiveRecord.Refreshmethod -
⚡ Unit test suites generates one NUnit XML output file for each platform
-
⚡ New built-in profiler (usable with Delphi 10.4+) – to profile a block of code, write the following
procedure TMyController.ProfilerSample1; begin NotProfiled(); //this line is not profiled //the following begin..end block will be profiled //timing will be saved in a \"profiler\" log begin var lProf := Profiler.Start(Context.ActionQualifiedName); DoSomething(); DoSomethingElse(); Render(\'Just executed \' + Context.ActionQualifiedName); end; // profiler writes automatically to the log NotProfiled(); //this line is not profiled end; procedure TMyController.DoSomething; begin begin var lProf := Profiler.Start(\'DoSomething\'); Sleep(100); end; end; procedure TMyController.DoSomethingElse; begin begin var lProf := Profiler.Start(\'DoSomethingElse\'); Sleep(100); DoSomething(); end; end; procedure TMyController.NotProfiled; begin Sleep(100); end;
The log contains the following lines – check the caller/called relationship shown using
>>and<<and the deep level[>>][ 1][MainControllerU.TMyController.ProfilerSample1] [profiler] [ >>][ 2][DoSomething] [profiler] [ <<][ 2][DoSomething][ELAPSED: 00:00:00.1088214] [profiler] [ >>][ 2][DoSomethingElse] [profiler] [ >>][ 3][DoSomething] [profiler] [ <<][ 3][DoSomething][ELAPSED: 00:00:00.1096617] [profiler] [ <<][ 2][DoSomethingElse][ELAPSED: 00:00:00.2188468] [profiler] [<<][ 1][MainControllerU.TMyController.ProfilerSample1][ELAPSED: 00:00:00.3277806] [profiler]To get more info check the \”profiling\” example.
All profiler logs are generated with a log level
info. If measured time is greater thanWarningThresholdthe log level iswarning.WarningThresholdis expressed in milliseconds and by default is equals to 1000. -
⚡ New
Contextproperty namedActionQualifiedNamewhich contains the currently executed action in the formUnitName.ClassName.ActionName. It is available where theContextproperty is available. Obviously is not available in theOnBeforeRoutingmiddleware events. -
⚡ Added ObjectPool and IntfObjectPool (and related unit tests). Thanks to our sponsor Vivaticket S.p.A.
-
⚡ Method
procedure Render(const AErrorCode: Integer; const AErrorMessage: string = \'\' ...has been renamed toRenderStatusMessagewith a better parameter names. -
⚡
IMVCJSONRPCExecutorsupports async call. Thanks to our sponsor Orion Law. Check the new Async sample insamples\\jsonrpc_with_published_objects\\. -
⚡ Removed
foTransientifTMVCActiveRecordFieldOptions. It became obsolete after introduction offoReadOnlyandfoWriteOnly. -
⚡ Improved
TMVCActiveRecordMiddleware. Now it can handle multiple connections for the same request. Also, you can completely omit the \’default\’ connection and just specify wich connection you want to use before starting to create yourTMVCActiveRecordinherited entities.
Bug Fix in 3.2.3-radium
- Fixed a rendering problem in swagger interface format in case of specific JSON structure
- Fix issue 594 (Thanks to biware-repo)
- Fix issue 595
- Fix issue 590
- Fix issue 490
- Fix Issue 583 (Thanks to Marcelo Jaloto)
- Fix Issue 585
More details about dmvcframework-3.2.3-radium fixes here
What\’s new in DMVCFramework-3.2.2-nitrogen
-
⚡New! Support for Delphi 11.x Alexandria
-
⚡New
TMVCRESTClientimplementation based on *Net components, the previous one was based on INDY Components (thanks to João Antônio Duarte). -
⚡New!
MVCJSONRPCAllowGETattribute 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.IMVCJSONRPCExecutorallows 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/ExecuteNotificationallows 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_luasample. -
✅ Improved! Under some heavy load circumnstances the logger queue can get full. Now
TThreadSafeQueueclass 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
TMVCLRUCacheimplementation. Very efficient implementation of LRU cache borrowed directly from DMSContainer -
⚡New
TMVCRedirectMiddlewareto handle HTTP redirections in a very simple and flexible way. -
⚡New!
TMVCActiveRecordsupports XML field type in PostgreSQL (in addition to JSON and JSONB). -
⚡New
OnContextCreateandOnContextDetroyedevents forTMVCEngine. -
⚡New! Added parameter
RootNodeinBodyForandBodyForListOf<T>methods, just like theBodyAs*methods. -
⚡New! Added
NullableTGUIDinMVCFramework.Nullables.pas. -
⚡New
property CustomIntfObject: IInterfaceinTWebContext. 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_primersample) -
✅ Improved! The unit tests fully test PostgreSQL, FirebirdSQL and SQLite while testing MVCActiveRecord framework. The other engines are tested using
activerecord_showcasesample project. -
✅ Improved! MVCActiveRecord does 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
nilto a nullable type and to check its state using the new propertyIsNullwhich is the negation of the already available propertyHasValue. -
✅ Improved! Now
TMVCStaticFileMiddlewareis able to manage high-level criteria to show/hide/mask specific files in the document 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 ofTMVCActiveRecorddescendants usingUnitOfWorkdesign pattern. Check the button \”Merge\” in demo \”activerecord_showcase\”. -
⚡ New! Added default filtering for
TMVCActiveRecord descendants(checkactiverecord_showcasesample project). -
⚡ 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
TMVCSQLGeneratorPostgreSQLtype 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.RemoveDefaultConnectionandTMVCActiveRecord.RemoveConnectionto avoid exceptions in case of not initialized connection. -
⚡ New! Added the new
MVCOwnedattribute 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) asMVCOwnedto allows the serialization to create or destroy object for you. -
✅ Improved!
Context.Dataproperty is now created on-demand using a lazy loading approach (expect an overall speed improvement). -
✅ Added
LogExceptionfunction inMVCFramework.Logger.pasto easily log exception in standard way. -
✅ Improved
MVCAREntitiesGeneratorproject – 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
ToJSONObjectandToJSONArrayto theIMVCRESTResponse. These methods automatically parse the response body and return aTJSONObjector aTJSONArrayrespectively. 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
TMVCJWTBlackListMiddlewareto 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!
MVCFromBodyattribute, 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!
MVCFromQueryStringattribute, useful to automatically inject a query string paramater an action paramater. For instance in the following action the query string paramsfromDateis automatically deserialized as aTDatevalue 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!
MVCFromHeaderattribute, useful to automatically inject a header value as an action parameter. For instance in the following action the header paramsXMyCoolHeaderis automatically deserialized asStringvalue 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!
MVCFromCookieattribute, useful to automatically inject a cookie value as an action parameter. For instance in the following action the cookieMyCoolCookieis automatically deserialized asTDatevalue 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
