2017-07-19 02:45:05 +02:00
![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)!
2019-09-01 20:35:19 +02:00
DelphiMVCFramework is the **most popular** Delphi project on GitHub!
2019-01-08 15:31:41 +01:00
2019-12-23 17:51:44 +01:00
**Daniele Teti is working on the [DelphiMVCFramework Handbook ](https://leanpub.com/delphimvcframework )! Stay tuned!**
![](docs/delphimvcframework_handbook_cover.png)
2019-01-08 15:31:41 +01:00
2019-09-01 20:35:19 +02:00
## How to install DMVCFramework
2019-09-12 16:36:51 +02:00
*It is not needed to download the git repository*. Just download the [latest version as a zip file ](https://github.com/danieleteti/delphimvcframework/releases/latest ) and you are ok.
2019-09-01 20:35:19 +02:00
If you want to participate to the testing phase (which usually contains brand new features) you can get the [latest Release Candidate version ](https://github.com/danieleteti/delphimvcframework/releases ).
2019-05-19 15:01:21 +02:00
Take in mind that, even if RCs are usually very stable, they are still not ready for production utilization.
2019-09-12 16:36:51 +02:00
## What users say about DMVCFramework
2019-03-06 14:52:43 +01:00
2020-04-12 12:38:00 +02:00
> "DMVCFramework and the Entity utility are fantastic!" -- Roberto
2019-03-06 14:52:43 +01:00
>"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
2019-09-01 20:35:19 +02:00
>"The best framework for creating web servers with Delphi! It is very easy to create Delphi servers and publish APIs and Rest resources.
2019-03-06 14:52:43 +01:00
Congratulations to Daniele Teti and all the staff for the excellent work!" -- Marcos N.
2019-09-01 20:35:19 +02:00
> 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
## DMVCFramework Main Features
2017-11-22 21:43:09 +01:00
2019-09-01 20:35:19 +02: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! (the guide is a bit outdated - a new book is being written by Daniele Teti. Let us know if you are interested in [DMVCFramework Handbook ](https://leanpub.com/delphimvcframework ))
2017-07-19 02:45:05 +02:00
* [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
2019-12-23 17:51:44 +01:00
* Commercially supported by [bit Time Professionals ](http://www.bittimeprofessionals.it ) (training, consultancy, custom development etc.)
2015-05-28 14:34:33 +02:00
* RESTful (RMM Level 3) compliant
2019-09-01 20:35:19 +02:00
* JSON-RPC 2.0 Support with automatic objects remotization (check [sample ](https://github.com/danieleteti/delphimvcframework/tree/master/samples/jsonrpc_with_published_objects ))
2016-02-19 12:09:14 +01:00
* Stable and solid, used by small/mid/big projects since 2010
2019-09-01 20:35:19 +02:00
* Very fast! (2.x was pretty fast and now, 3.x is 60% faster than the 2.x!)
2019-12-23 17:51:44 +01:00
* Support group at https://www.facebook.com/groups/delphimvcframework with more than 2700 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
2019-09-01 20:35:19 +02:00
* JSON Web Token Support (JWT) (check [sample ](https://github.com/danieleteti/delphimvcframework/tree/master/samples/jsonwebtoken ))
* Extendable using middleware - simple hooks to handle request/response (check [sample ](https://github.com/danieleteti/delphimvcframework/tree/master/samples/middleware ))
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
2019-09-01 20:35:19 +02:00
* Controllers inheritance! You can define your own base controller and inherit from it.
2015-05-28 14:34:33 +02:00
* Fancy URL with parameter mappings
2019-09-01 20:35:19 +02:00
* Specialized renders to generate text, HTML, JSON.
2018-02-26 16:22:49 +01:00
* 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
2019-12-23 17:51:44 +01:00
* Integrated REST Client
* Works with 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)
2019-09-01 20:35:19 +02:00
* Completely unit tested (more than 130 unit tests)
* There is a sample for each functionality (check the [dmvcframework_(yourversion)_samples.zip ](https://github.com/danieleteti/delphimvcframework/releases ))
2020-03-31 00:47:35 +02:00
* Server side generated pages using [Mustache for Delphi ](https://github.com/synopse/dmustache ) or [TemplatePro ](https://github.com/danieleteti/templatepro )
2019-03-06 14:52:43 +01:00
* Specific trainings are available (email to `professionals@bittime.it` for a date and a place)
2020-03-31 00:47:35 +02:00
* Push notifications support using [ServerSentEvents ](https://github.com/danieleteti/delphimvcframework/tree/master/samples/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
2017-07-19 02:45:05 +02:00
* Simple and [documented ](docs/ITDevCON%202013%20-%20Introduction%20to%20DelphiMVCFramework.pdf )
2019-09-12 16:36:51 +02:00
* Continuously tested for Delphi versions incompatibilities by the proud [compatibility maintainers ](COMPATIBILITY_MANTAINERS.MD )
2018-08-05 20:31:33 +02:00
2019-03-10 16:35:19 +01:00
## What's Cooking in the Lab
2018-08-05 20:31:33 +02:00
2019-10-09 23:14:56 +02:00
### DelphiMVCFramework 3.2.0-boron (currently in `RC` phase)
2019-10-09 23:44:44 +02:00
> WARNING! Considering the huge amount of features added in 3.1.1-beryllium during its RC phase, the dmvcframework-3.1.1-beryllium has been renamed to dmvcframework-3.2.0-boron
2020-01-06 16:51:54 +01:00
- New! Added Nullable support in MVCActiveRecord! Check *activerecord_showcase* sample.
2020-04-24 16:36:18 +02:00
2020-03-27 00:37:28 +01:00
- New! Added non autogenerated primary keys in MVCActiveRecord! Check *activerecord_showcase* sample.
2020-04-24 16:36:18 +02:00
2020-02-05 23:46:38 +01:00
- New! Complete support for nullable types in the default serializer.
2020-04-24 16:36:18 +02:00
- New! Added `ncCamelCase` and `ncPascalCase` to the available attribute formatters.
| MVCNameCase | Property/Field Name | Rendered Name |
| ------------ | --------------------- | --------------- |
| ncUpperCase | Cod_Article | COD_ARTICLE |
| ncLowerCase | Cod_Article | cod_article |
| ncPascalCase | Cod_Article | CodArticle |
| ncPascalCase | CodArticle | CodArticle |
| ncPascalCase | `_WITH__UNDERSCORES_` | WithUnderscores |
| ncCamelCase | Cod_Article | codArticle |
| ncCamelCase | CodArticle | codArticle |
| ncCamelCase | `_WITH__UNDERSCORES_` | WithUnderscores |
| | | |
2019-10-10 20:16:20 +02:00
- New! Added Swagger support (thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ) and [Geoffrey Smith ](https://github.com/geoffsmith82 ))
2020-04-24 16:36:18 +02:00
- New! **ObjectDict** function is the suggested way to render all the most common data types. It returns a `IMVCObjectDictionary` which is automatically rendered by the renders. Check the `renders.dproj` sample. Here's some example of the shining new `ObjectDict()`
**Example 1: Rendering a list of objects not freeing them after rendering**
*Classic*
```delphi
procedure TRenderSampleController.GetLotOfPeople;
begin
Render< TPerson > (GetPeopleList, False);
end;
```
*New approach with ObjectDict*
```delphi
procedure TRenderSampleController.GetLotOfPeople;
begin
Render(ObjectDict(False).Add('data', GetPeopleList));
end;
```
**Example 2: Rendering a list of objects and automatically free them after rendering**
*Classic*
```delphi
procedure TRenderSampleController.GetLotOfPeople;
begin
Render< TPerson > (GetPeopleList);
end;
```
*New approach with ObjectDict*
```delphi
procedure TRenderSampleController.GetLotOfPeople;
begin
Render(ObjectDict().Add('data', GetPeopleList));
end;
```
**Example 3: Rendering a list of objects adding links for HATEOAS support**
*Classic*
```delphi
procedure TRenderSampleController.GetPeople_AsObjectList_HATEOAS;
var
p: TPerson;
People: TObjectList< TPerson > ;
begin
People := TObjectList< TPerson > .Create(True);
{$REGION 'Fake data'}
p := TPerson.Create;
p.FirstName := 'Daniele';
p.LastName := 'Teti';
p.DOB := EncodeDate(1979, 8, 4);
p.Married := True;
People.Add(p);
p := TPerson.Create;
p.FirstName := 'John';
p.LastName := 'Doe';
p.DOB := EncodeDate(1879, 10, 2);
p.Married := False;
People.Add(p);
p := TPerson.Create;
p.FirstName := 'Jane';
p.LastName := 'Doe';
p.DOB := EncodeDate(1883, 1, 5);
p.Married := True;
People.Add(p);
{$ENDREGION}
Render< TPerson > (People, True,
procedure(const APerson: TPerson; const Links: IMVCLinks)
begin
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people/' + APerson.ID.ToString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json')
.Add('title', 'Details for ' + APerson.FullName);
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people')
.Add(HATEOAS.REL, 'people')
.Add(HATEOAS._TYPE, 'application/json');
end);
end;
```
*New approach with ObjectDict*
```delphi
procedure TRenderSampleController.GetPeople_AsObjectList_HATEOAS;
var
p: TPerson;
People: TObjectList< TPerson > ;
begin
People := TObjectList< TPerson > .Create(True);
{$REGION 'Fake data'}
p := TPerson.Create;
p.FirstName := 'Daniele';
p.LastName := 'Teti';
p.DOB := EncodeDate(1979, 8, 4);
p.Married := True;
People.Add(p);
p := TPerson.Create;
p.FirstName := 'John';
p.LastName := 'Doe';
p.DOB := EncodeDate(1879, 10, 2);
p.Married := False;
People.Add(p);
p := TPerson.Create;
p.FirstName := 'Jane';
p.LastName := 'Doe';
p.DOB := EncodeDate(1883, 1, 5);
p.Married := True;
People.Add(p);
{$ENDREGION}
Render(ObjectDict().Add('data', People,
procedure(const APerson: TObject; const Links: IMVCLinks)
begin
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people/' + TPerson(APerson).ID.ToString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json')
.Add('title', 'Details for ' + TPerson(APerson).FullName);
Links
.AddRefLink
.Add(HATEOAS.HREF, '/people')
.Add(HATEOAS.REL, 'people')
.Add(HATEOAS._TYPE, 'application/json');
end));
end;
```
`ObjectDict` is able to render multiple data sources (datasets, objectlists, objects or StrDict) at the same time using different casing, HATEOAS callbacks and modes.
```delphi
procedure TTestServerController.TestObjectDict;
var
lDict: IMVCObjectDictionary;
begin
lDict := ObjectDict(false)
.Add('ncUpperCase_List', GetDataSet, nil, dstAllRecords, ncUpperCase)
.Add('ncLowerCase_List', GetDataSet, nil, dstAllRecords, ncLowerCase)
.Add('ncCamelCase_List', GetDataSet, nil, dstAllRecords, ncCamelCase)
.Add('ncPascalCase_List', GetDataSet, nil, dstAllRecords, ncPascalCase)
.Add('ncUpperCase_Single', GetDataSet, nil, dstSingleRecord, ncUpperCase)
.Add('ncLowerCase_Single', GetDataSet, nil, dstSingleRecord, ncLowerCase)
.Add('ncCamelCase_Single', GetDataSet, nil, dstSingleRecord, ncCamelCase)
.Add('ncPascalCase_Single', GetDataSet, nil, dstSingleRecord, ncPascalCase)
.Add('meta', StrDict(['page'], ['1']));
Render(lDict);
end;
```
>ObjectDict is the suggested way to renders data. However, the other ones are still there and works as usual.
2019-09-01 20:35:19 +02:00
- New! Added SQLGenerator and RQL compiler for PostgreSQL, SQLite and MSSQLServer (in addition to MySQL, MariaDB, Firebird and Interbase)
2020-05-02 16:39:32 +02:00
- New! *MVCNameAs* attribute got the param `Fixed` (default: false). If `Fixed` is true, then the name is not processed by the `MVCNameCase` attribute assigned to the owner type.
2019-10-10 20:16:20 +02:00
- New! Added support for interfaces serialization - now it is possible to serialize Spring4D collections (thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
2019-11-27 19:04:06 +01:00
- New! Added support for Spring4D Nullable Types - check (thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
2020-02-26 13:25:00 +01:00
- New! Added `OnRouterLog` event to log custom information for each request (thanks to [Andrea Ciotti ](https://github.com/andreaciotti ) for the first implementation and its PR)
2020-04-29 17:53:29 +02:00
- New! Optionally load system controllers (those who provide `/describeserver.info` , `/describeplatform.info` and `/serverconfig.info` system actions) setting `Config[TMVCConfigKey.LoadSystemControllers] := 'false';` in the configuration block.
2019-12-17 14:52:11 +01:00
- Improved! Now the router consider `Accept:*/*` compatible for every `MVCProduces` values
2019-03-10 16:35:19 +01:00
- Improved! Greatly improved support for [HATEOAS ](https://en.wikipedia.org/wiki/HATEOAS ) in renders. Check `TRenderSampleController.GetPeople_AsObjectList_HATEOS` and all the others actions end with `HATEOS` in `renders.dproj` sample)
2019-03-08 09:33:41 +01:00
```delphi
2020-05-02 16:39:32 +02:00
//Now is really easy to add "links" property automatically for each collection element while rendering
2019-03-10 16:35:19 +01:00
Render< TPerson > (People, True,
2019-05-10 00:46:03 +02:00
procedure(const APerson: TPerson; const Links: IMVCLinks)
begin
Links.AddRefLink
.Add(HATEOAS.HREF, '/people/' + APerson.ID.ToString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json')
.Add('title', 'Details for ' + APerson.FullName);
Links.AddRefLink
.Add(HATEOAS.HREF, '/people')
.Add(HATEOAS.REL, 'people')
.Add(HATEOAS._TYPE, 'application/json');
end);
2019-03-10 16:29:18 +01:00
2019-03-10 16:35:19 +01:00
//Datasets have a similar anon method to do the same thing
Render(lDM.qryCustomers, False,
2019-05-10 00:46:03 +02:00
procedure(const DS: TDataset; const Links: IMVCLinks)
2019-03-10 16:35:19 +01:00
begin
2019-05-10 00:46:03 +02:00
Links.AddRefLink
.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, 'application/json');
Links.AddRefLink
.Add(HATEOAS.HREF, '/customers/' + DS.FieldByName('cust_no').AsString + '/orders')
.Add(HATEOAS.REL, 'orders')
.Add(HATEOAS._TYPE, 'application/json');
2019-03-10 16:35:19 +01:00
end);
//Single object rendering allows HATEOAS too!
Render(lPerson, False,
2019-05-10 00:46:03 +02:00
procedure(const AObject: TObject; const Links: IMVCLinks)
2019-03-10 16:35:19 +01:00
begin
2019-05-10 00:46:03 +02:00
Links.AddRefLink
.Add(HATEOAS.HREF, '/people/' + TPerson(AObject).ID.ToString)
.Add(HATEOAS.REL, 'self')
.Add(HATEOAS._TYPE, TMVCMediaType.APPLICATION_JSON);
Links.AddRefLink
.Add(HATEOAS.HREF, '/people')
.Add(HATEOAS.REL, 'people')
.Add(HATEOAS._TYPE, TMVCMediaType.APPLICATION_JSON);
end);
2019-03-10 16:32:39 +01:00
2019-09-01 20:35:19 +02:00
```
2019-03-10 16:35:19 +01:00
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` )
2020-01-04 12:53:53 +01:00
- Change! `TMVCACtiveRecord.GetByPK<T>` raises an exception by default if the record is not found - optionally can returns `nil` using new parameter `RaiseExceptionIfNotFound`
2019-01-18 18:11:27 +01:00
- New! `contains` clause has been added in the RQL compiler for Firebird and Interbase
2019-01-18 19:35:37 +01:00
- 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\`
2019-02-21 18:11:14 +01:00
- New! `TMVCActiveRecord.DeleteAll` deletes all the records from a table
- New! `TMVCActiveRecord.DeleteRQL` deletes records using an `RQL` expression as `where` clause.
2020-02-05 23:46:38 +01:00
- New! `TMVCActiveRecord.Store` which automatically executes Insert or Update considering primary key value.
2020-04-08 18:04:45 +02:00
- New! `TMVCActiveRecord` allows to use table name and field name with spaces (currently supported only by the PostgreSQL compiler).
2019-10-15 09:43:29 +02:00
- New! Microsoft SQLServer Support in `MVCActiveRecord` and RQL (*thanks to one of the biggest Delphi based company in Italy which heavily uses DMVCFramework* and *[DMSContainer](http://www.bittimeprofessionals.it/prodotti/dmscontainer)* )
- New! SQLite support in `MVCActiveRecord` and RQL, so that `MVCActiveRecord` can be used also for Delphi mobile projects!
2019-11-05 14:40:39 +01:00
- Default JSON Serializer can verbatim pass properties with type `JsonDataObjects.TJSONObject` without using `string` as carrier of JSON
2019-02-21 18:11:14 +01:00
- Improved! `ActiveRecordShowCase` sample is much better now.
2020-03-23 18:51:57 +01:00
- Improved! All `ActiveRecord` methods which retrieve records can now specify the data type of each parameter (using Delphi's `TFieldType` enumeration).
2019-02-24 20:43:06 +01:00
- Improved! In case of unhandled exception `TMVCEngine` is compliant with the default response content-type (usually it did would reply using `text/plain` ).
2019-10-09 23:14:56 +02:00
- Added! New overloads for all the Log\* calls. Now it is possible to call `LogD(lMyObject)` to get logged `lMyObject` as JSON (custom type serializers not supported in log).
2019-05-19 14:35:34 +02:00
- New! `StrDict(array of string, array of string)` function allows to render a dictionary of strings in a really simple way. See the following action sample.
```delphi
procedure TMy.GetPeople(const Value: Integer);
begin
if Value mod 2 < > 0 then
begin
raise EMVCException.Create(HTTP_STATUS.NotAcceptable, 'We don''t like odd numbers');
end;
Render(
StrDict(
['id', 'message'],
['123', 'We like even numbers, thank you for your ' + Value.ToString]
));
end;
```
2019-05-02 17:38:57 +02:00
- New! Custom Exception Handling (Based on work of [David Moorhouse ](https://github.com/fastbike )). Sample "custom_exception_handling" show how to use it.
2020-03-24 17:55:25 +01:00
2019-03-19 12:06:13 +01:00
- Improved! Exceptions rendering while using MIME types different to `application/json` .
2020-03-24 17:55:25 +01:00
2019-12-23 17:51:44 +01:00
- SSL Server support for `TMVCListener` (Thanks to [Sven Harazim ](https://github.com/landrix ))
2020-03-24 17:55:25 +01:00
2019-10-09 23:14:56 +02:00
- Improved! Datasets serialization speed improvement. In some case the performance [improves of 2 order of magnitude ](https://github.com/danieleteti/delphimvcframework/issues/205#issuecomment-479513158 ). (Thanks to https://github.com/pedrooliveira01)
2020-03-24 17:55:25 +01:00
2019-05-19 14:35:34 +02:00
- New! Added `in` operator in RQL parser (Thank you to [João Antônio Duarte ](https://github.com/joaoduarte19 ) for his initial work on this)
2020-03-24 17:55:25 +01:00
2019-05-10 00:46:03 +02:00
- New! Added `TMVCActiveRecord.Count<T>(RQL)` to count record based on RQL criteria
2020-03-24 17:55:25 +01:00
2020-03-31 00:47:35 +02:00
- New! `TMVCActiveRecord` can handle non autogenerated primary key.
2019-05-02 17:38:57 +02:00
- New! Experimental (alpha stage) support for Android servers!
2020-03-24 17:55:25 +01:00
2019-05-10 00:46:03 +02:00
- New! Added support for `X-HTTP-Method-Override` to work behind corporate firewalls.
2020-03-24 17:55:25 +01:00
2019-05-19 14:35:34 +02:00
- New Sample! Server in DLL
2020-03-24 17:55:25 +01:00
2019-11-27 19:04:06 +01:00
- Added new method in the dataset helper to load data into a dataset from a specific JSONArray property of a JSONObject `procedure TDataSetHelper.LoadJSONArrayFromJSONObjectProperty(const AJSONObjectString: string; const aPropertyName: String);`
2020-03-24 17:55:25 +01:00
2019-10-09 23:14:56 +02:00
- Improved! New constants defined in `HTTP_STATUS` to better describe the http status response.
2020-03-24 17:55:25 +01:00
2019-10-09 23:14:56 +02:00
- Improved! Now Firebird RQL' SQLGenerator can include primary key in `CreateInsert` if not autogenerated.
2020-03-24 17:55:25 +01:00
2019-11-03 16:16:35 +01:00
- New! Added support for `TArray<String>` , `TArray<Integer>` and `TArray<Double>` in default JSON serializer (Thank you [Pedro Oliveira ](https://github.com/pedrooliveira01 ))
2020-03-24 17:55:25 +01:00
2019-07-24 20:48:22 +02:00
- Improved JWT Standard Compliance! Thanks to [Vinicius Sanchez ](https://github.com/viniciussanchez ) for his work on [issue #241 ](https://github.com/danieleteti/delphimvcframework/issues/241 )
2020-03-24 17:55:25 +01:00
2019-10-09 23:14:56 +02:00
- Improved! DMVCFramework now has 130+ unit tests that checks its functionalities at each build!
2020-03-24 17:55:25 +01:00
2019-10-09 23:14:56 +02:00
- New! `StrToJSONObject` function to safely parse a string into a JSON object.
2020-03-24 17:55:25 +01:00
2019-09-25 09:14:09 +02:00
- New! Serialization callback for custom `TDataSet` descendants serialization in `TMVCJsonDataObjectsSerializer` .
```delphi
procedure TMainForm.btnDataSetToJSONArrayClick(Sender: TObject);
var
lSer: TMVCJsonDataObjectsSerializer;
lJArray: TJSONArray;
begin
FDQuery1.Open();
lSer := TMVCJsonDataObjectsSerializer.Create;
try
lJArray := TJSONArray.Create;
try
lSer.DataSetToJsonArray(FDQuery1, lJArray, TMVCNameCase.ncLowerCase, [],
procedure(const aField: TField; const aJsonObject: TJSONObject; var Handled: Boolean)
begin
if SameText(aField.FieldName, 'created_at') then
begin
aJsonObject.S['year_and_month'] := FormatDateTime('yyyy-mm', TDateTimeField(aField).Value);
Handled := True;
end;
end);
//The json objects will not contains "created_at" anymore, but only "year_and_month".
Memo1.Lines.Text := lJArray.ToJSON(false);
finally
lJArray.Free;
end;
finally
lSer.Free;
end;
end;
```
2019-09-01 20:35:19 +02:00
- New! Shortcut render' methods which simplify RESTful API development
2020-03-31 00:47:35 +02:00
- `procedure Render201Created(const Location: String = ''; const Reason: String = 'Created'); virtual;`
- ` procedure Render202Accepted(const HREF: String; const ID: String; const Reason: String = 'Accepted'); virtual;`
- `procedure Render204NoContent(const Reason: String = 'No Content'); virtual;`
2019-10-15 09:43:29 +02:00
2019-11-03 16:16:35 +01:00
- Added de/serializing iterables (e.g. generic lists) support without `MVCListOf` attribute (Thank you to [João Antônio Duarte ](https://github.com/joaoduarte19 )).
2019-10-15 09:43:29 +02:00
It is now possible to deserialize a generic class like this:
```delphi
TGenericEntity< T: class > = class
private
FCode: Integer;
FItems: TObjectList< T > ;
FDescription: string;
public
constructor Create;
destructor Destroy; override;
property Code: Integer read FCode write FCode;
property Description: string read FDescription write FDescription;
// MVCListOf(T) < - No need
property Items: TObjectList< T > read FItems write FItems;
end;
```
Before it was not possible because you should add the `MVCListOf` attribute to the `TObjectList` type property.
2019-11-28 19:04:26 +01:00
- New! The **MVCAREntitiesGenerator** can optionally register all the generated entities also in the `ActiveRecordMappingRegistry` (Thanks to [Fabrizio Bitti ](https://twitter.com/fabriziobitti ) from [bit Time Software ](http://www.bittime.it ))
2020-05-04 09:48:51 +02:00
- New! Children objects lifecycle management in `TMVCActiveRecord` (methods `AddChildren` and `RemoveChildren` ). Really useful to manage child objects such relations or derived properties and are safe in case of multiple addition of the same object as children.
```delphi
//Having the following declaration
type
[MVCNameCase(ncCamelCase)]
[MVCTable('authors')]
TAuthor = class(TPersonEntityBase)
private
fBooks: TEnumerable< TBookRef > ;
[MVCTableField('full_name')]
fFullName: string;
function GetBooks: TEnumerable< TBookRef > ;
public
[MVCNameAs('full_name')]
property FullName: string read fFullName write fFullName;
property Books: TEnumerable< TBookRef > read GetBooks;
end;
//method GetBooks can be implemented as follows:
implementation
function TAuthor.GetBooks: TEnumerable< TBookRef > ;
begin
if fBooks = nil then
begin
fBooks := TMVCActiveRecord.Where< TBookRef > ('author_id = ?', [ID]);
AddChildren(fBooks); //fBooks will be freed when self will be freed
end;
Result := fBooks;
end;
```
2020-05-02 16:39:32 +02:00
- **JSON-RPC Improvements**
- New! Added `TMVCJSONRPCExecutor.ConfigHTTPClient` to fully customize the inner `THTTPClient` (e.g. `ConnectionTimeout` , `ResponseTimeout` and so on)
- Improved! JSONRPC Automatic Object Publishing can not invoke inherited methods if not explicitly defined with `MVCInheritable` attribute.
- New! Calling `<jsonrpcendpoint>/describe` returns the methods list available for that endpoint.
- New! Full support for named parameters in JSON-RPC call (server and client)
- Positional parameters example
```delphi
procedure TMainForm.btnSubtractClick(Sender: TObject);
var
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.Add(StrToInt(edtValue1.Text));
lReq.Params.Add(StrToInt(edtValue2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
edtResult.Text := lResp.Result.AsInteger.ToString;
end;
```
- Named parameters example
```delphi
procedure TMainForm.btnSubtractWithNamedParamsClick(Sender: TObject);
var
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.AddByName('Value1', StrToInt(Edit1.Text));
lReq.Params.AddByName('Value2', StrToInt(Edit2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
Edit3.Text := lResp.Result.AsInteger.ToString;
end;
```
- Check [official JSONRPC 2.0 documentation ](https://www.jsonrpc.org/specification#examples ) for more examples.
- New! JSONRPC Hooks for published objects
```delphi
//Called before as soon as the HTTP arrives
procedure TMyPublishedObject.OnBeforeRouting(const JSON: TJDOJsonObject);
//Called before the invoked method
procedure TMyPublishedObject.OnBeforeCall(const JSONRequest: TJDOJsonObject);
//Called just before to send response to the client
procedure TMyPublishedObject.OnBeforeSendResponse(const JSONResponse: TJDOJsonObject);
```
2020-04-19 12:23:55 +02:00
2020-02-03 10:51:40 +01:00
- **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).
- **Breaking Change!** Middleware `OnAfterControllerAction` are now invoked in the same order of `OnBeforeControllerAction` (previously were invoked in reversed order).
2020-04-24 16:36:18 +02:00
- **Deprecated!** `TDataSetHolder` is deprecated! Use the shining new `ObjectDict(boolean)` instead.
2020-02-03 10:51:40 +01:00
2020-03-12 20:38:07 +01:00
- Added ability to serialize/deserialize types enumerated by an array of mapped values (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
```delphi
type
TMonthEnum = (meJanuary, meFebruary, meMarch, meApril);
TEntityWithEnums = class
private
FMonthMappedNames: TMonthEnum;
FMonthEnumName: TMonthEnum;
FMonthOrder: TMonthEnum;
public
// List items separated by comma or semicolon
[MVCEnumSerializationType(estEnumMappedValues,
'January,February,March,April')]
property MonthMappedNames: TMonthEnum
read FMonthMappedNames write FMonthMappedNames;
[MVCEnumSerializationType(estEnumName)]
property MonthEnumName: TMonthEnum
read FMonthEnumName write FMonthEnumName;
[MVCEnumSerializationType(estEnumOrd)]
property MonthOrder: TMonthEnum read FMonthOrder write FMonthOrder;
end;
...
```
2019-10-15 12:51:08 +02:00
- New Installation procedure!
- Open the project group (select the correct one from the following table)
- Build all
- Install the design-time package (`dmvcframeworkDT`)
- Add the following paths in the Delphi Library Path (here, `C:\DEV\dmvcframework` is the `dmvcframework` main folder)
- `C:\DEV\dmvcframework\sources`
- `C:\DEV\dmvcframework\lib\loggerpro`
- `C:\DEV\dmvcframework\lib\swagdoc\Source`
- `C:\DEV\dmvcframework\lib\dmustache`
2019-01-18 18:11:27 +01:00
|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` |
2019-03-10 16:32:39 +01:00
|Delphi 10.0 Seattle| `packages\d100\dmvcframework_group.groupproj` |
2019-01-13 19:18:57 +01:00
2020-05-02 16:39:32 +02:00
### Bug Fixes in 3.2.0-boron
- Fixed! [issue38 ](https://github.com/danieleteti/delphimvcframework/issues/38 )
- Fixed! [issue184 ](https://github.com/danieleteti/delphimvcframework/issues/184 )
- Fixed! [issue278 ](https://github.com/danieleteti/delphimvcframework/issues/278 )
- Fixed! [issue164 ](https://github.com/danieleteti/delphimvcframework/issues/164 )
- Fixed! [issue182 ](https://github.com/danieleteti/delphimvcframework/issues/182 )
- Fixed! [issue232 ](https://github.com/danieleteti/delphimvcframework/issues/232 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
- Fixed! [issue289 ](https://github.com/danieleteti/delphimvcframework/issues/289 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
- Fixed! [issue291 ](https://github.com/danieleteti/delphimvcframework/issues/291 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
- Fixed! [issue305 ](https://github.com/danieleteti/delphimvcframework/issues/305 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
- Fixed! [issue312 ](https://github.com/danieleteti/delphimvcframework/issues/312 )
- Fixed! [issue330 ](https://github.com/danieleteti/delphimvcframework/issues/330 )
- Fixed! [issue333 ](https://github.com/danieleteti/delphimvcframework/issues/333 )
- Fixed! [issue334 ](https://github.com/danieleteti/delphimvcframework/issues/334 )
- Fixed! [issue336 ](https://github.com/danieleteti/delphimvcframework/issues/336 )
- Fixed! [issue337 ](https://github.com/danieleteti/delphimvcframework/issues/337 )
- Fixed! [issue338 ](https://github.com/danieleteti/delphimvcframework/issues/338 )
- Fixed! [issue345 ](https://github.com/danieleteti/delphimvcframework/issues/345 )
- Fixed! [issue349 ](https://github.com/danieleteti/delphimvcframework/issues/349 )
- Fixed! [issue350 ](https://github.com/danieleteti/delphimvcframework/issues/350 )
- Fixed! [issue355 ](https://github.com/danieleteti/delphimvcframework/issues/355 )
- Fixed! [issue356 ](https://github.com/danieleteti/delphimvcframework/issues/356 )
- Fixed! [issue362 ](https://github.com/danieleteti/delphimvcframework/issues/362 )
- Fixed! [issue363 ](https://github.com/danieleteti/delphimvcframework/issues/363 )
- Fixed! [issue364 ](https://github.com/danieleteti/delphimvcframework/issues/364 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
- Fixed! [issue366 ](https://github.com/danieleteti/delphimvcframework/issues/366 )
2020-05-03 12:45:39 +02:00
- Fixed! [issue376 ](https://github.com/danieleteti/delphimvcframework/issues/376 ) (Thanks to [João Antônio Duarte ](https://github.com/joaoduarte19 ))
2020-05-02 16:39:32 +02:00
- Fixed! Has been patched a serious security bug affecting deployment configurations which uses internal WebServer to serve static files (do not affect all Apache, IIS or proxied deployments). Thanks to **Stephan Munz** to have discovered it. *Update to dmvcframework-3.2-RC5+ is required for all such kind of deployments.*
2019-12-23 17:51:44 +01:00
## DelphiMVCFramework 3.1.0-lithium (Current Release)
2018-10-23 16:18:34 +02:00
- 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` )
2018-08-05 20:31:33 +02:00
- `Config[TMVCConfigKey.FallbackResource]` is served only if request path is empty or `/` .
2018-10-23 16:18:34 +02:00
- New! Now the JSON-RPC executor provides methods to handle HTTP headers for JSON-RPC requests and notifications.
2019-09-30 00:05:46 +02:00
- `TDataSetHolder` is a new render 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 )
2018-08-08 15:43:37 +02:00
- `404` and `500` status code returns always a `text/plain` content-type
- Refactored ISAPI sample
2018-08-08 17:11:45 +02:00
- 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!
2018-12-17 00:39:29 +01:00
- New! Added `MAX_REQUEST_SIZE` for limiting the size of the incoming HTTP requests. IDE Expert is updated too!
2018-10-23 16:18:34 +02:00
- New! Added method `TMVCJsonDataObjectsSerializer.ListToJsonArray`
- New! `TMVCResponse` for handle generic (non error) response
- New! `TMVCErrorResponse` for handle generic error response
2018-10-31 01:07:23 +01:00
- New! Added class `TMVCActiveRecordList` used in the manual `TMVCActiveRecord` programming
2018-10-23 16:18:34 +02:00
- New! Added `gzip` compression support in addition to `deflate` in `TCompressionMiddleware`
2018-08-08 17:11:45 +02:00
- FIX for [issue #143 ](https://github.com/danieleteti/delphimvcframework/issues/143 )
2018-10-23 16:18:34 +02:00
- 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
2018-10-30 13:53:01 +01:00
- 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).
2018-10-31 01:07:23 +01:00
- 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
2018-10-31 01:07:23 +01:00
- New! Support for Spring4d nullable types (check `samples\renders_spring4d_nullables` )
2018-11-21 22:11:58 +01:00
- New! `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even datamodules) through a JSON-RPC 2.0 interface!
2018-12-17 00:39:29 +01:00
- *Breaking Change!* The JSON RPC Client layer is now interface based.
2018-08-05 20:31:33 +02:00
2016-09-10 15:52:56 +02:00
## Roadmap
2017-07-19 02:45:05 +02:00
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.
2019-12-23 17:51:44 +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 [bit Time Professionals website ](http://www.bittimeprofessionals.it ). bit Time Professionals is the company behind DelphiMVCFramework, all the main developers works there.
2015-05-28 14:34:33 +02:00
2017-01-29 18:39:27 +01:00
## Release Notes
2019-12-23 17:51:44 +01:00
#### 3.1.0 (lithium)
- `TMVCActiveRecord` framework
- `TMVCActiveRecordController` with automatic RESTful interface generation and permissions handling
- EntityProcessor for `TMVCActiveRecordController` to handle complex cases
- JSON-RPC executor allows to configure HTTP headers for JSON-RPC requests and notifications.
- `TDataSetHolder`
- `404` and `500` status code returns always a `text/plain` content-type
- Speed improvement!
- `MAX_REQUEST_SIZE` can now limit the size of the incoming HTTP requests.
- `TMVCResponse` can handle generic (non error) responses
- `gzip` compression support in addition to `deflate` in `TCompressionMiddleware`
- `TCompressionMiddleware` has been renamed in `TMVCCompressionMiddleware`
- Support for Spring4d nullable types (check `samples\renders_spring4d_nullables` )
- `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even data modules) through a JSON-RPC 2.0 interface!
- *Breaking Change!* The JSON RPC Client layer is now interface based.
#### 3.0.0 (hydrogen)
2018-02-26 16:22:49 +01:00
- First release of the 3.0.0 version
2019-12-23 17:51:44 +01:00
#### 2.1.3 (lithium)
2017-01-29 19:08:26 +01:00
- FIX https://github.com/danieleteti/delphimvcframework/issues/64
- Added unit tests to avoid regressions
2019-09-01 20:35:19 +02:00
2019-12-23 17:51:44 +01:00
#### 2.1.2 (helium)
2017-01-29 18:39:27 +01:00
- 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+)
2019-12-23 17:51:44 +01:00
#### 2.1.1 (hydrogen)
2017-01-29 18:39:27 +01:00
- 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)
2019-09-01 20:35:19 +02:00
- ADDED support for Boolean values in datasets serialization
2017-01-29 18:39:27 +01:00
- 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.
2017-07-19 02:45:05 +02:00
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).
2019-09-01 20:35:19 +02:00
The project contains 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.
```
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)')]
2015-11-30 17:15:16 +01:00
[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-15 22:51:36 +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
2015-06-15 22:51:36 +02:00
2016-06-16 22:13:35 +02:00
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 22:51:36 +02:00
2015-06-15 23:39:39 +02:00
```delphi
2015-06-15 23:44:45 +02:00
uses
2016-06-16 22:13:35 +02:00
MVCFramework.Server,
MVCFramework.Server.Impl;
2015-06-15 23:44:45 +02:00
var
2016-06-16 22:13:35 +02:00
LServerListener: IMVCListener;
2015-06-15 23:44:45 +02:00
begin
2016-06-16 22:13:35 +02:00
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
```
2015-06-15 22:51:36 +02:00
2016-06-16 22:13:35 +02:00
If you want to add a layer of security (in its WebModule you should add the security middleware):
2015-06-15 22:51:36 +02:00
2015-06-15 23:39:39 +02:00
```delphi
2015-06-15 23:44:45 +02:00
uses
2016-06-16 22:13:35 +02:00
MVCFramework.Server,
MVCFramework.Server.Impl,
MVCFramework.Middleware.Authentication;
2015-06-15 23:44:45 +02:00
procedure TTestWebModule.WebModuleCreate(Sender: TObject);
begin
2016-06-16 22:13:35 +02:00
FMVCEngine := TMVCEngine.Create(Self);
2015-06-15 22:51:36 +02:00
2016-06-16 22:13:35 +02:00
// Add Yours Controllers
FMVCEngine.AddController(TYourController);
2015-06-15 22:51:36 +02:00
2016-06-16 22:13:35 +02:00
// 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
2016-06-16 22:13:35 +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
2016-06-16 22:13:35 +02:00
uses
MVCFramework.Server,
MVCFramework.Server.Impl;
2015-06-15 23:44:45 +02:00
var
2016-06-16 22:13:35 +02:00
LServerListenerCtx: IMVCListenersContext;
2015-06-15 23:44:45 +02:00
begin
2016-06-16 22:13:35 +02:00
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).