delphimvcframework/README.md

426 lines
19 KiB
Markdown
Raw Normal View History

![DelphiMVCFramework Logo](docs/dmvcframework_logofacebook.png)
2016-10-14 12:27:52 +02:00
2019-01-08 15:31:41 +01:00
# DelphiMVCFramework 3.1.0-lithium is [here](https://github.com/danieleteti/delphimvcframework/releases/tag/v3.1.0-lithium)!
DelphiMVCFramework is the most popular Delphi project on github!
Daniele is working on the [DelphiMVCFramework Handbook](https://leanpub.com/delphimvcframework)! Stay tuned!
2019-03-06 14:52:43 +01:00
## What users says about DMVCFramework
>"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.
2017-11-22 21:43:09 +01:00
## DelphiMVCFramework Main Features
2016-02-27 10:27:01 +01:00
* Simple to use, check the ["Getting Started: 5 minutes guide"](https://danieleteti.gitbooks.io/delphimvcframework/content/chapter_getting_started.html) and you will be up and running in 5 minutes or less!
* [Project Roadmap](roadmap.md) is always public
2016-11-18 14:09:54 +01:00
* More than 40 samples to learn all the features and be proficient and productive
2015-05-28 14:34:33 +02:00
* RESTful (RMM Level 3) compliant
2019-01-08 15:31:41 +01:00
* JSON-RPC 2.0 Support with automatic objects remotization
2016-02-19 12:09:14 +01:00
* Stable and solid, used by small/mid/big projects since 2010
2019-01-08 15:31:41 +01:00
* Very fast! (3.x is 60% faster than the 2.x)
* Support group at https://www.facebook.com/groups/delphimvcframework with more than 2100 active members
2018-02-26 16:22:49 +01:00
* Can be used in load balanced environment
2016-05-21 22:15:35 +02:00
* Wizard for the Delphi IDE. It makes DelphiMVCFramework even more simple to use!
2016-02-19 12:09:14 +01:00
* Optional session support
2016-05-21 22:15:35 +02:00
* JSON Web Token Support (JWT)
2016-02-19 12:09:14 +01:00
* Extendable using middlewares (simple hooks to handle request/response)
2018-02-26 16:22:49 +01:00
* Flexible yet simple to use, authorization/authentication framework based on industry standards.
* HTTP Basic Authentication
* JWT Authentication
* Custom Authentication
2016-05-21 22:15:35 +02:00
* CORS support
2018-02-26 16:22:49 +01:00
* Controllers inheritance! You can define your own base controller and inherith from it.
2015-05-28 14:34:33 +02:00
* Fancy URL with parameter mappings
2018-02-26 16:22:49 +01:00
* Specialied renders to generate text, HTML, JSON.
* Powerful and customizable mapper to serialize/deserialize data.
2015-10-12 14:17:59 +02:00
* Can be packaged as stand alone server, apache module (XE6 or better) and ISAPI dll
2015-05-28 14:34:33 +02:00
* Integrated RESTClient
2019-03-06 14:52:43 +01:00
* Works with XE7, XE8, Delphi 10 Seattle, Delphi 10.1 Berlin, Delphi 10.2 Tokyo, Delphi 10.3 Rio
2018-02-26 16:22:49 +01:00
* Works on Linux (Delphi 10.2 Tokyo or better)
2015-05-28 14:34:33 +02:00
* Completely unit tested
2016-02-19 12:09:14 +01:00
* There is a sample for each functionality
2015-05-28 14:34:33 +02:00
* There is a complete set of trainings about it, but the samples are included in the project
2015-11-15 18:37:14 +01:00
* Server side generated pages using Mustache (https://mustache.github.io/) for Delphi (https://github.com/synopse/dmustache)
2019-03-06 14:52:43 +01:00
* Specific trainings are available (email to `professionals@bittime.it` for a date and a place)
2018-02-26 16:22:49 +01:00
* Messaging extension using ServerSentEvents
2019-03-06 14:52:43 +01:00
* Automatic documentation through `/system/describeserver.info`
2016-02-19 12:09:14 +01:00
* Driven by its huge community (Facebook group https://www.facebook.com/groups/delphimvcframework)
2017-01-29 19:08:26 +01:00
* Semantic Versioning
* Simple and [documented](docs/ITDevCON%202013%20-%20Introduction%20to%20DelphiMVCFramework.pdf)
2019-03-06 14:52:43 +01:00
* Continuosly tested for Delphi versions incompatibilities by the proud [compatibility mantainers](COMPATIBILITY_MANTAINERS.MD)
## What's New
2019-01-13 19:18:57 +01:00
### DelphiMVCFramework 3.1.1-beryllium (currently in `RC` phase)
- New! Added SQLGenerator and RQL compiler for PostgreSQL (in addition to MySQL, MariaDB, Firebird and Interbase)
- Improved! Greatly improved support for [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) in renders. Check `TRenderSampleController.GetPeople_AsObjectList_HATEOS` in `renders.dproj` sample)
```delphi
//Now is really easy to add "_links" property automatically for each collection element while rendering
Render<TPerson>(People, True,
procedure(const Person: TPerson; const Dict: TMVCStringDictionary)
begin
Dict['x-ref'] := '/api/people/' + Person.ID;
Dict['x-child-ref'] := '/api/people/' + Person.ID + '/child';
end);
```
2019-01-13 19:18:57 +01:00
- Better packages organization (check `packages` folder)
- New! `TMVCActiveRecord.Count` method (e.g. `TMVCActiveRecord.Count(TCustomer)` returns the number of records for the entity mapped by the class `TCustomer`)
- Change! `TMVCACtiveRecord.GetByPK<T>` raises an exception if the record is not found
- New! `contains` clause has been added in the RQL compiler for Firebird and Interbase
- New! `TMVCAnalyticsMiddleware` to do automatic analytics on the API (generates a CSV file). Based on an idea by Nirav Kaku (https://www.facebook.com/nirav.kaku). Check the sample in `\samples\middleware_analytics\`
- New! `TMVCActiveRecord.DeleteAll` deletes all the records from a table
- New! `TMVCActiveRecord.DeleteRQL` deletes records using an `RQL` expression as `where` clause.
- New! Microsoft SQLServer Support in ActiveRecord and RQL (thanks to one of the biggest Delphi based company in Italy which heavily uses DMVCFramework)
- Improved! `ActiveRecordShowCase` sample is much better now.
- Improved! In case of unhandled exception `TMVCEngine` is compliant with the default response content-type (usually it did would reply using `text/plain`).
- Fix! [issue184](https://github.com/danieleteti/delphimvcframework/issues/184).
- Breaking Change! In `MVCActiveRecord` attribute `MVCPrimaryKey` has been removed and merged with `MVCTableField`, so now `TMVCActiveRecordFieldOption` is a set of `foPrimaryKey`, `foAutoGenerated`, `foTransient` (check `activerecord_showcase.dproj` sample).
- Added! New overloads for all the Log\* calls. Now it is possibile to call `LogD(lMyObject)` to get logged `lMyObject` as JSON.
- Fixed! [issue164](https://github.com/danieleteti/delphimvcframework/issues/164)
2019-03-06 12:00:56 +01:00
- Fixed! [issue182](https://github.com/danieleteti/delphimvcframework/issues/182)
- New Installation procedure! Just open the project group, build all and install the design-time package (which is `dmvcframeworkDT`)
|Delphi Version|Project Group|
|---|---|
|Delphi 10.3 Rio| `packages\d103\dmvcframework_group.groupproj`|
|Delphi 10.2 Tokyo| `packages\d102\dmvcframework_group.groupproj`|
|Delphi 10.1 Berlin| `packages\d101\dmvcframework_group.groupproj`|
For older Delphi versions still there aren't complete packages available, but DMVCFramework is usable from XE7 without any issues. If you use a version previous of `Delphi 10.1 Berlin` and you want to contribute, please provide your group project using the distributed packages as example.
2019-01-13 19:18:57 +01:00
### DelphiMVCFramework 3.1.0-lithium
- New! Added `TMVCActiveRecord` framework (check sample `activerecord_showcase` and `activerecord_crud`)
- New! Added `TMVCActiveRecordController` (check sample `activerecord_crud`)
- Automatic permissions handling for `TMVCActiveRecordController` (check sample `activerecord_crud`)
- EntityProcessor for `TMVCActiveRecordController` (check sample `activerecord_crud`)
- `Config[TMVCConfigKey.FallbackResource]` is served only if request path is empty or `/`.
- New! Now the JSON-RPC executor provides methods to handle HTTP headers for JSON-RPC requests and notifications.
- `TDataSetHolder` is a new render that is able to render a dataset with a set of custom metadata (eg `count`,`page` etc). Check [issue #137](https://github.com/danieleteti/delphimvcframework/issues/137)
- `404` and `500` status code returns always a `text/plain` content-type
- Refactored ISAPI sample
- Speed improvement! Removed enhanced visibility for action methods. Now only public and published methods can be used as actions.
- `TMVCController.Create` is `virtual`! Now on your base controllers can be even more powerful!
- New! Added `MAX_REQUEST_SIZE` for limiting the size of the incoming HTTP requests. IDE Expert is updated too!
- New! Added method `TMVCJsonDataObjectsSerializer.ListToJsonArray`
- New! `TMVCResponse` for handle generic (non error) response
- New! `TMVCErrorResponse` for handle generic error response
- New! Added class `TMVCActiveRecordList` used in the manual `TMVCActiveRecord` programming
- New! Added `gzip` compression support in addition to `deflate` in `TCompressionMiddleware`
- FIX for [issue #143](https://github.com/danieleteti/delphimvcframework/issues/143)
- FIX for [issue #141](https://github.com/danieleteti/delphimvcframework/issues/141)
- Removed deprecated methods in `IRESTResponse`
- FIX misspelled header name in `IRESTResponse`
- New! Added `gzip` and `deflate` support in `TRestClient` when reading responses
- `TCompressionMiddleware` has been renamed in `TMVCCompressionMiddleware`
- New! `TMVCCompressionMiddleware` is added by IDE Expert by default
- Removed the old JSON serializer based on `System.JSON.pas', now the only available JSON serializer is based on [JsonDataObjects](https://github.com/ahausladen/JsonDataObjects) parser (Thank you Andreas Hausladen).
- Changed! Custom Types Serializer *must* be registered by media-type only, without charset definition (e.g. just `application/json` and not `application/json;charset=utf-8`)
- Changed! `IMVCTypeSerializer` is more powerful and simple to use!
2018-10-31 01:14:48 +01:00
- Sending wrongly formatted JSON now returns a more correctly `400 Bad Request` and not `500 Internal Server Error` as in the previous versions
- New! Support for Spring4d nullable types (check `samples\renders_spring4d_nullables`)
- New! `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even datamodules) through a JSON-RPC 2.0 interface!
- *Breaking Change!* The JSON RPC Client layer is now interface based.
2015-05-28 14:34:33 +02:00
2018-02-26 16:22:49 +01:00
## How to correctly get the source
It is not needed to download the git repository. Just download the [latest version as zip file](https://github.com/danieleteti/delphimvcframework/releases/tag/v3.0.0-hydrogen) and you are ok.
2016-09-06 10:55:41 +02:00
2016-09-10 15:52:56 +02:00
## Roadmap
DelphiMVCFramework roadmap is always updated as-soon-as the features planned are implemented. Check the roadmap [here](roadmap.md).
2016-09-10 15:52:56 +02:00
2015-12-04 17:01:01 +01:00
## Trainings, consultancy or custom development service
2015-12-04 15:49:10 +01:00
As you know, good support on open source software is a must for professional users.
2015-12-04 17:01:55 +01:00
If you need trainings, consultancy or custom developments on DelphiMVCFramework, send an email to *dmvcframework at bittime dot it*. Alternatively you can send a request using the [contacts forms](http://www.bittimeprofessionals.it/contatti) on [bittimeprofessionals website](http://www.bittimeprofessionals.it). bit Time Professionals is the company behind DelphiMVCFramework, al the main developers works there.
2015-05-28 14:34:33 +02:00
2018-02-26 16:22:49 +01:00
### Using mapping framework in Delphi Starter Edition
A lot of users ask about it, now is possible to use the mapper framework also in Delphi Started Edition. To enable the "StarterEditionMode" open ```sources\dmvcframework.inc``` and remove the dot (.) after the curly brace in the following line
2017-01-03 13:41:11 +01:00
```{.$DEFINE STARTEREDITION}```
become
```{$DEFINE STARTEREDITION}```
2015-05-28 14:34:33 +02:00
2017-01-29 18:39:27 +01:00
## Release Notes
2018-02-26 16:22:49 +01:00
**3.0.0 (hydrogen)**
- First release of the 3.0.0 version
2017-01-29 19:08:26 +01:00
**2.1.3 (lithium)**
- FIX https://github.com/danieleteti/delphimvcframework/issues/64
- Added unit tests to avoid regressions
2017-01-29 18:39:27 +01:00
**2.1.2 (helium)**
- FIX for Delphi versions who don't have ```TJSONBool``` (Delphi XE8 or older)
- Added new conditional define in dmvcframework.inc: JSONBOOL (defined for Delphi Seattle+)
**2.1.1 (hydrogen)**
- Updated the IDE Expert to show the current version of the framework
- FIX to the mapper about the datasets null values (needs to be checked in old Delphi versions)
- ADDED support for boolean values in datasets serialization
- ADDED unit tests about Mapper and dataset fields nullability
- The current version is available in constant ```DMVCFRAMEWORK_VERSION``` defined in ```MVCFramework.Commons.pas```
2018-05-15 10:32:25 +02:00
## Samples and documentation
2015-05-28 14:34:33 +02:00
DMVCFramework is provided with a lot of examples focused on specific functionality.
All samples are in [Samples](samples) folder.
2016-02-27 10:27:01 +01:00
Check the [DMVCFramework Developer Guide](https://danieleteti.gitbooks.io/delphimvcframework/content/) (work in progress).
2015-05-28 14:34:33 +02:00
2018-05-15 10:32:25 +02:00
# Getting Started
2016-09-06 10:55:41 +02:00
Below the is a basic sample of a DMVCFramework server wich can be deployed as standa-alone application, as an Apache module or as ISAPI dll. This flexibility is provided by the Delphi WebBroker framework (built-in in Delphi since Delphi 4).
The project containes an IDE Expert which make creating DMVCFramework project a breeze. However not all the Delphi version are supported, so here's the manual version (which is not complicated at all).
2015-06-16 10:36:35 +02:00
2017-01-29 18:39:27 +01:00
To create this server, you have to create a new ```Delphi Projects -> WebBroker -> WebServerApplication```. Then add the following changes to the webmodule.
2015-06-16 10:36:35 +02:00
```delphi
unit WebModuleUnit1;
interface
uses System.SysUtils, System.Classes, Web.HTTPApp, MVCFramework {this unit contains TMVCEngine class};
type
TWebModule1 = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
MVC: TMVCEngine;
public
{ Public declarations }
end;
var
WebModuleClass: TComponentClass = TWebModule1;
implementation
{$R *.dfm}
uses UsersControllerU; //this is the unit where is defined the controller
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
MVC := TMVCEngine.Create(Self);
2016-09-06 10:55:41 +02:00
MVC.Config[TMVCConfigKey.DocumentRoot] := 'public_html'; //if you need some static html, javascript, etc (optional)
2015-06-16 10:36:35 +02:00
MVC.AddController(TUsersController); //see next section to know how to create a controller
end;
procedure TWebModule1.WebModuleDestroy(Sender: TObject);
begin
MVC.Free;
end;
end.
```
2015-06-16 10:49:53 +02:00
Remember that the files inside the redist folder *must* be in the executable path or in the system path. If starting the server whithin the IDE doesn't works, try to run the executable outside the IDE and check the dependencies.
2015-06-16 10:36:35 +02:00
That's it! You have just created your first DelphiMVCFramework. Now you have to add a controller to respond to the http request.
2018-05-15 10:32:25 +02:00
## Sample Controller
2015-05-28 14:34:33 +02:00
Below a basic sample of a DMVCFramework controller with 2 action
2015-06-15 23:39:39 +02:00
```delphi
2015-06-15 23:44:45 +02:00
unit UsersControllerU;
interface
uses
MVCFramework;
type
[MVCPath('/users')]
TUsersController = class(TMVCController)
public
2016-06-23 12:40:12 +02:00
2015-06-15 23:44:45 +02:00
//The following action will be with a GET request like the following
//http://myserver.com/users/3
[MVCPath('/($id)')]
[MVCProduces('application/json')]
2015-06-15 23:44:45 +02:00
[MVCHTTPMethod([httpGET])]
2016-06-23 12:40:12 +02:00
[MVCDoc('Returns a user as a JSON object')]
procedure GetUser(id: Integer);
//The following action will be with a GET request like the following
//http://myserver.com/users
[MVCPath('/')]
[MVCProduces('application/json')]
[MVCHTTPMethod([httpGET])]
2015-12-18 14:29:40 +01:00
[MVCDoc('Returns the users list as a JSON Array of JSON Objects')]
2016-06-23 12:40:12 +02:00
procedure GetUsers;
2015-06-15 23:44:45 +02:00
2015-06-16 10:39:46 +02:00
//The following action will be with a PUT request like the following
2015-06-15 23:44:45 +02:00
//http://myserver.com/users/3
//and in the request body there should be a serialized TUser
[MVCPath('/($id)')]
[MVCProduce('application/json')]
2015-06-16 10:39:46 +02:00
[MVCHTTPMethod([httpPUT])]
2015-12-18 14:29:40 +01:00
[MVCDoc('Update a user')]
2016-06-23 12:40:12 +02:00
procedure UpdateUser(id: Integer);
2015-06-16 10:39:46 +02:00
//The following action will respond to a POST request like the following
//http://myserver.com/users
//and in the request body there should be the new user to create as json
[MVCPath]
[MVCProduce('application/json')]
[MVCHTTPMethod([httpPOST])]
2015-12-18 14:29:40 +01:00
[MVCDoc('Create a new user, returns the id of the new user')]
2016-06-23 12:40:12 +02:00
procedure CreateUser;
2015-06-15 23:44:45 +02:00
end;
implementation
uses
MyTransactionScript; //contains actual data access code
{ TUsersController }
2016-06-23 12:40:12 +02:00
procedure TUsersController.GetUsers;
var
Users: TObjectList<TUser>;
begin
Users := GetUsers;
Render(Users);
end;
2015-06-15 23:44:45 +02:00
2016-06-23 12:40:12 +02:00
procedure TUsersController.GetUser(id: Integer);
2015-06-15 23:44:45 +02:00
var
User: TUser;
begin
2016-06-23 12:40:12 +02:00
User := GetUserById(id);
2015-06-15 23:44:45 +02:00
Render(User);
end;
2016-06-23 12:40:12 +02:00
procedure TUsersController.UpdateUser(id: Integer);
2015-06-15 23:44:45 +02:00
var
User: TUser;
begin
2016-06-23 12:40:12 +02:00
User := Context.Request.BodyAs<TUser>;
UpdateUser(id, User);
2015-06-15 23:44:45 +02:00
Render(User);
end;
2016-06-23 12:40:12 +02:00
procedure TUsersController.CreateUser;
2015-06-16 10:39:46 +02:00
var
User: TUser;
begin
2016-06-23 12:40:12 +02:00
User := Context.Request.BodyAs<TUser>;
2015-06-16 10:39:46 +02:00
CreateUser(User);
Render(User);
end;
2015-06-15 23:44:45 +02:00
end.
2015-06-15 23:39:39 +02:00
```
2015-06-16 10:49:53 +02:00
Now you have a performant RESTful server wich respond to the following URLs:
- GET /users/($id) (eg. /users/1, /users/45 etc)
- PUT /users/($id) (eg. /users/1, /users/45 etc with the JSON data in the request body)
- POST /users (the JSON data must be in the request body)
2018-05-15 10:32:25 +02:00
### Quick Creation of DelphiMVCFramework Server
If you dont plan to deploy your DMVCFramework server behind a webserver (apache or IIS) you can also pack more than one listener application server into one single executable. In this case, the process is a bit different and involves the creation of a listener context. However, create a new server is a simple task:
2015-06-15 23:39:39 +02:00
```delphi
2015-06-15 23:44:45 +02:00
uses
MVCFramework.Server,
MVCFramework.Server.Impl;
2015-06-15 23:44:45 +02:00
var
LServerListener: IMVCListener;
2015-06-15 23:44:45 +02:00
begin
LServerListener := TMVCListener.Create(TMVCListenerProperties.New
.SetName('Listener1')
.SetPort(5000)
.SetMaxConnections(1024)
.SetWebModuleClass(YourServerWebModuleClass)
);
LServerListener.Start;
LServerListener.Stop;
2015-06-15 23:44:45 +02:00
end;
2015-06-15 23:39:39 +02:00
```
If you want to add a layer of security (in its WebModule you should add the security middleware):
2015-06-15 23:39:39 +02:00
```delphi
2015-06-15 23:44:45 +02:00
uses
MVCFramework.Server,
MVCFramework.Server.Impl,
MVCFramework.Middleware.Authentication;
2015-06-15 23:44:45 +02:00
procedure TTestWebModule.WebModuleCreate(Sender: TObject);
begin
FMVCEngine := TMVCEngine.Create(Self);
// Add Yours Controllers
FMVCEngine.AddController(TYourController);
// Add Security Middleware
FMVCEngine.AddMiddleware(TMVCBasicAuthenticationMiddleware.Create(
TMVCDefaultAuthenticationHandler.New
.SetOnAuthentication(
procedure(const AUserName, APassword: string;
AUserRoles: TList<string>; var IsValid: Boolean;
const ASessionData: TDictionary<String, String>)
begin
IsValid := AUserName.Equals('dmvc') and APassword.Equals('123');
end
)
));
2015-06-15 23:44:45 +02:00
end;
2015-06-15 23:39:39 +02:00
```
2015-05-28 14:34:33 +02:00
In stand alone mode you can work with a context that supports multiple listeners servers:
2015-05-28 14:34:33 +02:00
2015-06-15 23:39:39 +02:00
```delphi
uses
MVCFramework.Server,
MVCFramework.Server.Impl;
2015-06-15 23:44:45 +02:00
var
LServerListenerCtx: IMVCListenersContext;
2015-06-15 23:44:45 +02:00
begin
LServerListenerCtx := TMVCListenersContext.Create;
LServerListenerCtx.Add(TMVCListenerProperties.New
.SetName('Listener1')
.SetPort(6000)
.SetMaxConnections(1024)
.SetWebModuleClass(WebModuleClass1)
);
LServerListenerCtx.Add(TMVCListenerProperties.New
.SetName('Listener2')
.SetPort(7000)
.SetMaxConnections(1024)
.SetWebModuleClass(WebModuleClass2)
);
LServerListenerCtx.StartAll;
2015-06-15 23:44:45 +02:00
end;
2015-06-15 23:39:39 +02:00
```
2015-05-28 14:34:33 +02:00
2018-05-15 10:32:25 +02:00
### Links
2015-05-28 14:34:33 +02:00
Feel free to ask questions on the "Delphi MVC Framework" facebook group (https://www.facebook.com/groups/delphimvcframework).