Skip to content

DelphiMVCFramework 3.2.2-nitrogen

Compare
Choose a tag to compare
@danieleteti danieleteti released this 15 Sep 08:54
· 478 commits to master since this release

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 each ExecuteRequest/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 and OnContextDetroyed events for TMVCEngine.

  • ⚡New! Added parameter RootNode in BodyFor and BodyForListOf<T> methods, just like the BodyAs* methods.

  • ⚡New! Added NullableTGUID in MVCFramework.Nullables.pas.

  • ⚡New property CustomIntfObject: IInterface in TWebContext. 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 property IsNull which is the negation of the already available property HasValue.

  • ✅ 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 sample samples\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 of TMVCActiveRecord descendants using UnitOfWork 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 and TMVCActiveRecord.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) as MVCOwned 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 in MVCFramework.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 and ToJSONArray to the IMVCRESTResponse. These methods automatically parse the response body and return a TJSONObject or a TJSONArray 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 of ToJSONObject, or is not a JSONArray in case of ToJSONArray) 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 the TMVCJWTAuthenticationMiddleware.

    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) and OnNewJWTToBlackList (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 params fromDate is automatically deserialized as a TDate 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 params XMyCoolHeader is automatically deserialized as String 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 cookie MyCoolCookie is automatically deserialized as TDate 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 and CheckIfMatch allows a better security without adding complexity to the controller code - check avoid_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

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