diff --git a/.gitignore b/.gitignore
index 6a1cf11c..d94145c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -144,3 +144,4 @@ samples/WineCellarSample/winecellarclient_mobile/Android/Debug/styles.xml
samples/WineCellarSample/winecellarclient_mobile/Android/Debug/styles-v21.xml
samples/WineCellarSample/winecellarclient_mobile/Android/Debug/WineCellarMobileClient.classes/classes.dex
samples/apachemodule/Apache24/logs/httpd.pid
+samples/session_file_based/Win32/DEBUG/sessions/
diff --git a/README.md b/README.md
index b73f38a3..5541abe8 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
- [What users say about DMVCFramework](#what-users-say-about-dmvcframework)
- [What's New in dmvcframework-3.3.0-fluorine (last stable version)](#whats-new-in-dmvcframework-330-fluorine-last-stable-version)
- [What's New in the next "repo version" a.k.a. 3.4.0-neon](#whats-new-in-the-next-repo-version-aka-340-neon)
- - [Hystorical Versions](#hystorical-versions)
+ - [Old Versions](#old-versions)
- [What's New in dmvcframework-3.2.3-radium](#whats-new-in-dmvcframework-323-radium)
- [Bug Fix in 3.2.3-radium](#bug-fix-in-323-radium)
- [What's new in DelphiMVCFramework-3.2.2-nitrogen](#whats-new-in-delphimvcframework-322-nitrogen)
@@ -214,6 +214,8 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
> "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.3.0-fluorine (last stable version)
@@ -231,20 +233,400 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
## What's New in the next "repo version" a.k.a. 3.4.0-neon
-- Added support for dotEnv multiline keys - added dotEnv show case
-- Added MSHeap memory manager for Win32 and Win64 (https://github.com/RDP1974/DelphiMSHeap)
+- ⚡ Added support for dotEnv multiline keys - added dotEnv show case
+
+- ⚡ Added MSHeap memory manager for Win32 and Win64 (https://github.com/RDP1974/DelphiMSHeap)
+
- 🐞 FIX [Issue 664](https://github.com/danieleteti/delphimvcframework/issues/664) Thanks to [MPannier](https://github.com/MPannier)
+
- 🐞 FIX [Issue 667](https://github.com/danieleteti/delphimvcframework/issues/667)
+
+- 🐞 FIX [Issue 680](https://github.com/danieleteti/delphimvcframework/issues/680)
+
- 🐞 FIX Wrong comparison in checks for ro/RW/PK fields in `TMVCActiveRecord`
-- Wizard updated to be dotEnv aware
-- Removed Controller Application Session (very seldom used but potentially breaking change)
-- Removed Middlewares in favor of a simpler alternative named "Filters"
- - Added Protocol Filters
- - Added Controller Filters
-- `TMVCRouterLogHandlerProc` changed prototype (breaking change)
+
+- 🐞 FIX wrong default initialization for JWT (thanks to Flavio Basile)
+
+- ⚡ Wizard updated to be dotEnv aware
+
+- ⚡ Added "Load Style" methods to `TMVCActiveRecord` as suggested by https://github.com/danieleteti/delphimvcframework/issues/675
+
+- ⚡ Better error message in case of serialization of `TArray`
+
+- ⚡ Improved CORS handling - [Issue 679](https://github.com/danieleteti/delphimvcframework/issues/679) (Thanks to [David Moorhouse](https://github.com/fastbike))
+
+- ⚡ Improved serialization of `TObjectList` (however `ObjectDict` is still the preferred way to serialize multiple datasets).
+
+- ⚡ Added static method for easier cloning of FireDAC dataset into `TFDMemTable`.
+
+ - `class function CloneFrom(const FDDataSet: TFDDataSet): TFDMemTable`
+
+ - Check sample "function_actions_showcase.dproj" for more info.
+
+- ⚡ Functional Actions
+
+ - In addition to the classic `procedure` based actions, now it's possibile to use functions as actions. The `Result` variable is automatically rendered and, if it is an object, its memory is freed.
+
+ ```pascal
+ 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;
+
+ { actions returning objects }
+ [MVCPath('/objects/single')]
+ function GetSingleObject: TPerson;
+ [MVCPath('/objects/multiple')]
+ function GetMultipleObjects: TObjectList;
+
+ { actions returning datasets }
+ [MVCPath('/datasets/single')]
+ function GetSingleDataSet: TDataSet;
+ [MVCPath('/datasets/multiple')]
+ function GetMultipleDataSet: TEnumerable;
+ [MVCPath('/datasets/multiple2')]
+ function GetMultipleDataSet2: IMVCObjectDictionary;
+
+ { customize response headers }
+ [MVCPath('/headers')]
+ function GetWithCustomHeaders: TObjectList;
+ end;
+ ```
+
+ Check sample "function_actions_showcase.dproj" for more info.
+
+- ⚡ Improved `TMVCResponse` type to better suits the new functional actions.
+
+ `TMVCResponse` can 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).
+
+ **Message based responses**
+
+ ```pascal
+ function TMyController.GetMVCResponse: TMVCResponse;
+ begin
+ Result := MVCResponse(HTTP_STATUS.OK, 'My Message');
+ end;
+ ```
+
+ Produces
+
+ ```json
+ {
+ "message":"My Message"
+ }
+ ```
+
+
+
+ **Data based response with single object**
+
+ ```pascal
+ function TMyController.GetMVCResponse2: TMVCResponse;
+ begin
+ Result := MVCResponse(HTTP_STATUS.OK, TPerson.Create('Daniele','Teti', 99));
+ end;
+ ```
+
+ Produces
+
+ ```json
+ {
+ "data": {
+ "firstName": "Daniele",
+ "lastName": "Teti",
+ "age": 99
+ }
+ }
+ ```
+
+ **Data based response with list of objects**
+
+ ```pascal
+ function TMyController.GetMVCResponse3: TMVCResponse;
+ begin
+ Result := MVCResponse(HTTP_STATUS.OK,
+ TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ );
+ end;
+ ```
+
+ Produces
+
+ ```json
+ {
+ "data": [
+ {
+ "firstName": "Daniele",
+ "lastName": "Teti",
+ "age": 99
+ },
+ {
+ "firstName": "Peter",
+ "lastName": "Parker",
+ "age": 25
+ },
+ {
+ "firstName": "Bruce",
+ "lastName": "Banner",
+ "age": 45
+ }
+ ]
+ }
+ ```
+
+ **Data dictionary based response with `IMVCObjectDictionary` **
+
+ ```pascal
+ function TMyController.GetMVCResponseWithObjectDictionary: IMVCResponse;
+ begin
+ Result := MVCResponse(
+ HTTP_STATUS.OK,
+ ObjectDict()
+ .Add('employees', TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ )
+ .Add('customers', TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ )
+ );
+ end;
+ ```
+
+ Produces
+
+ ```json
+ {
+ "employees": [
+ {
+ "firstName": "Daniele",
+ "lastName": "Teti",
+ "age": 99
+ },
+ {
+ "firstName": "Peter",
+ "lastName": "Parker",
+ "age": 25
+ },
+ {
+ "firstName": "Bruce",
+ "lastName": "Banner",
+ "age": 45
+ }
+ ],
+ "customers": [
+ {
+ "firstName": "Daniele",
+ "lastName": "Teti",
+ "age": 99
+ },
+ {
+ "firstName": "Peter",
+ "lastName": "Parker",
+ "age": 25
+ },
+ {
+ "firstName": "Bruce",
+ "lastName": "Banner",
+ "age": 45
+ }
+ ]
+ }
+ ```
+
+- Removed `statuscode` and `reasonstring` from exception's JSON rendering.
+
+- ⚡ New! NamedQueries support for TMVCActiveRecord.
+
+ - `MVCNamedSQLQuery` allows to define a "named query" which is, well, a SQL query with a name. Then such query can be used by the method `SelectByNamedQuery`. 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. Check the example below.
+
+ ```delphi
+ type
+ [MVCTable('customers')]
+ [MVCNamedSQLQuery('RatingLessThanPar', 'select * from customers where rating < ? order by code, city desc')]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*firebird*/ * from customers where rating = ? order by code, city desc',
+ TMVCActiveRecordBackEnd.FirebirdSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*postgres*/ * from customers where rating = ? order by code, city desc',
+ TMVCActiveRecordBackEnd.PostgreSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*all*/ * from customers where rating = ? order by code, city desc')]
+ TCustomer = class(TCustomEntity)
+ private
+ // usual field declaration
+ end;
+
+ //** then in the code
+
+ Log('** Named SQL Query');
+ Log('QuerySQL: RatingLessThanPar');
+ var lCustomers := TMVCActiveRecord.SelectByNamedQuery('RatingLessThanPar', [4], [ftInteger]);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ Log('QuerySQL: RatingEqualsToPar');
+ lCustomers := TMVCActiveRecord.SelectByNamedQuery('RatingEqualsToPar', [3], [ftInteger]);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ ```
+
+ The same approach is available for RQL query, which can be used also for Count and Delete operations but doesnt allows to specify the backend (because RQL has an actual compiler to adapt the generated SQL to each RDBMS)
+
+ ```delphi
+ type
+ [MVCTable('customers')]
+ [MVCNamedSQLQuery('RatingLessThanPar', 'select * from customers where rating < ? order by code, city desc')]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*firebird*/ * from customers where rating = ? order by code, city desc',
+ TMVCActiveRecordBackEnd.FirebirdSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*postgres*/ * from customers where rating = ? order by code, city desc',
+ TMVCActiveRecordBackEnd.PostgreSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*all*/ * from customers where rating = ? order by code, city desc')]
+ [MVCNamedRQLQuery('RatingLessThanPar', 'lt(rating,%d);sort(+code,-city)')]
+ [MVCNamedRQLQuery('RatingEqualsToPar', 'eq(rating,%d);sort(+code,-city)')]
+ TCustomer = class(TCustomEntity)
+ private
+ // usual field declaration
+ end;
+
+ //** then in the code
+
+ Log('** Named RQL Query');
+ Log('QueryRQL: RatingLessThanPar');
+ lCustomers := TMVCActiveRecord.SelectRQLByNamedQuery('RatingLessThanPar', [4], 1000);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ Log('QueryRQL: RatingEqualsToPar');
+ lCustomers := TMVCActiveRecord.SelectRQLByNamedQuery('RatingEqualsToPar', [3], 1000);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ ```
+
+ Now, having SQL and RQL named queries, it is possibile to have an entity which is not mapped on a specific table but loaded only by named queries.
+
+ ```delphi
+ type
+ [MVCEntityActions([eaRetrieve])]
+ [MVCNamedSQLQuery('CustomersInTheSameCity',
+ 'SELECT c.id, c.DESCRIPTION, c.city, c.code, c.rating, (SELECT count(*) - 1 FROM customers c2 WHERE c2.CITY = c.CITY) customers_in_the_same_city ' +
+ 'FROM CUSTOMERS c WHERE city IS NOT NULL AND city <> '''' ORDER BY customers_in_the_same_city')]
+ TCustomerStats = class(TCustomEntity) {not mapped on an actual table or view}
+ private
+ [MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
+ fID: NullableInt64;
+ [MVCTableField('code')]
+ fCode: NullableString;
+ [MVCTableField('description')]
+ fCompanyName: NullableString;
+ [MVCTableField('city')]
+ fCity: string;
+ [MVCTableField('rating')]
+ fRating: NullableInt32;
+ [MVCTableField('customers_in_the_same_city')]
+ fCustomersInTheSameCity: Int32;
+ public
+ property ID: NullableInt64 read fID write fID;
+ property Code: NullableString read fCode write fCode;
+ property CompanyName: NullableString read fCompanyName write fCompanyName;
+ property City: string read fCity write fCity;
+ property Rating: NullableInt32 read fRating write fRating;
+ property CustomersInTheSameCity: Int32 read fCustomersInTheSameCity write fCustomersInTheSameCity;
+ end;
+
+
+ //** then in the code
+
+ procedure TMainForm.btnVirtualEntitiesClick(Sender: TObject);
+ begin
+ var lCustStats := TMVCActiveRecord.SelectByNamedQuery('CustomersInTheSameCity', [], []);
+ try
+ for var lCustomer in lCustStats do
+ begin
+ Log(Format('%4d - %8.5s - %s - (%d other customers in the same city)', [
+ lCustomer.ID.ValueOrDefault,
+ lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault,
+ lCustomer.CustomersInTheSameCity
+ ]));
+ end;
+ finally
+ lCustStats.Free;
+ end;
+ end;
+
+
+ ```
+
+
-## Hystorical Versions
+## Old Versions
### What's New in dmvcframework-3.2.3-radium
diff --git a/ideexpert/DMVC.Expert.CodeGen.NewControllerUnit.pas b/ideexpert/DMVC.Expert.CodeGen.NewControllerUnit.pas
index 43108ee1..f9e3d738 100644
--- a/ideexpert/DMVC.Expert.CodeGen.NewControllerUnit.pas
+++ b/ideexpert/DMVC.Expert.CodeGen.NewControllerUnit.pas
@@ -104,12 +104,19 @@ var
lActionFiltersMethodsImpl: string;
lCRUDMethodsIntf: string;
lCRUDMethodsImpl: string;
+ lBOClassesIntf: string;
+ lBOClassesImpl: string;
begin
lControllerUnit := sControllerUnit;
+
lIndexMethodIntf := sIndexMethodIntf;
lIndexMethodImpl := Format(sIndexMethodImpl, [FControllerClassName]);
+
lCRUDMethodsIntf := sCRUDMethodsIntf;
lCRUDMethodsImpl := Format(sCRUDMethodsImpl, [FControllerClassName]);
+ lBOClassesIntf := sBOClassesIntf;
+ lBOClassesImpl := Format(sBOClassesImpl, ['TPerson']);
+
if not FCreateIndexMethod then
begin
@@ -121,6 +128,8 @@ begin
begin
lCRUDMethodsIntf := '';
lCRUDMethodsImpl := '';
+ lBOClassesIntf := '';
+ lBOClassesImpl := '';
end;
lActionFiltersMethodsIntf := sActionFiltersIntf;
@@ -138,7 +147,18 @@ begin
(BorlandIDEServices as IOTAModuleServices).GetNewModuleAndClassName('',
lUnitIdent, lFormName, lFileName);
Result := TSourceFile.Create(sControllerUnit,
- [lUnitIdent, FControllerClassName, lIndexMethodIntf, lIndexMethodImpl, lActionFiltersMethodsIntf, lActionFiltersMethodsImpl, lCRUDMethodsIntf, lCRUDMethodsImpl]);
+ [
+ lUnitIdent,
+ FControllerClassName,
+ lIndexMethodIntf,
+ lIndexMethodImpl,
+ lActionFiltersMethodsIntf,
+ lActionFiltersMethodsImpl,
+ lCRUDMethodsIntf,
+ lCRUDMethodsImpl,
+ lBOClassesIntf,
+ lBOClassesImpl
+ ]);
end;
{ TNewJSONRPCUnitEx }
@@ -155,7 +175,6 @@ function TNewJSONRPCUnitEx.NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: string): IOTAFile;
var
lUnitIdent: string;
-// lFormName: string;
lFileName: string;
lDummy: String;
begin
diff --git a/ideexpert/DMVC.Expert.CodeGen.Templates.pas b/ideexpert/DMVC.Expert.CodeGen.Templates.pas
index 0cc5763a..39be6dbc 100644
--- a/ideexpert/DMVC.Expert.CodeGen.Templates.pas
+++ b/ideexpert/DMVC.Expert.CodeGen.Templates.pas
@@ -130,14 +130,18 @@ resourcestring
// 3 - Sample Methods - Implementation
// 4 - Action Filters - Interface
// 5 - Action Filters - Implementation
+ // 8 - BO - Interface
+ // 9 - BO - Implementation
+
sControllerUnit = 'unit %0:s;' + sLineBreak +
sLineBreak +
'interface' + sLineBreak +
sLineBreak +
'uses' + sLineBreak +
- ' MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons;' + sLineBreak +
+ ' MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections;' + sLineBreak +
sLineBreak +
'type' + sLineBreak +
+ '%8:s' + sLineBreak +
' [MVCPath(''/api'')]' + sLineBreak +
' %1:s = class(TMVCController) ' + sLineBreak +
' public' + sLineBreak +
@@ -154,6 +158,7 @@ resourcestring
'%5:s' + sLineBreak +
'%7:s' + sLineBreak +
sLineBreak +
+ '%9:s' + sLineBreak +
'end.' + sLineBreak;
sIndexMethodIntf =
@@ -162,6 +167,7 @@ resourcestring
' procedure Index;' + sLineBreak + sLineBreak +
' [MVCPath(''/reversedstrings/($Value)'')]' + sLineBreak +
' [MVCHTTPMethod([httpGET])]' + sLineBreak +
+ ' [MVCProduces(TMVCMediaType.TEXT_PLAIN)]' + sLineBreak +
' procedure GetReversedString(const Value: String);' + sLineBreak;
// 0 - Class Name
@@ -179,45 +185,66 @@ resourcestring
sCRUDMethodsIntf =
sLineBreak +
' public' + sLineBreak +
- ' //Sample CRUD Actions for a "Customer" entity' + sLineBreak +
- ' [MVCPath(''/customers'')]' + sLineBreak +
+ ' //Sample CRUD Actions for a "People" entity' + sLineBreak +
+ ' [MVCPath(''/people'')]' + sLineBreak +
' [MVCHTTPMethod([httpGET])]' + sLineBreak +
- ' procedure GetCustomers;' + sLineBreak + sLineBreak +
- ' [MVCPath(''/customers/($id)'')]' + sLineBreak +
+ ' function GetPeople: TObjectList;' + sLineBreak + sLineBreak +
+ ' [MVCPath(''/people/($ID)'')]' + sLineBreak +
' [MVCHTTPMethod([httpGET])]' + sLineBreak +
- ' procedure GetCustomer(id: Integer);' + sLineBreak + sLineBreak +
- ' [MVCPath(''/customers'')]' + sLineBreak +
+ ' function GetPerson(ID: Integer): TPerson;' + sLineBreak + sLineBreak +
+ ' [MVCPath(''/people'')]' + sLineBreak +
' [MVCHTTPMethod([httpPOST])]' + sLineBreak +
- ' procedure CreateCustomer;' + sLineBreak + sLineBreak +
- ' [MVCPath(''/customers/($id)'')]' + sLineBreak +
+ ' function CreatePerson([MVCFromBody] Person: TPerson): TMVCResponse;' + sLineBreak + sLineBreak +
+ ' [MVCPath(''/people/($ID)'')]' + sLineBreak +
' [MVCHTTPMethod([httpPUT])]' + sLineBreak +
- ' procedure UpdateCustomer(id: Integer);' + sLineBreak + sLineBreak +
- ' [MVCPath(''/customers/($id)'')]' + sLineBreak +
+ ' function UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): TMVCResponse;' + sLineBreak + sLineBreak +
+ ' [MVCPath(''/people/($ID)'')]' + sLineBreak +
' [MVCHTTPMethod([httpDELETE])]' + sLineBreak +
- ' procedure DeleteCustomer(id: Integer);' + sLineBreak + sLineBreak;
+ ' function DeletePerson(ID: Integer): TMVCResponse;' + sLineBreak + sLineBreak;
sCRUDMethodsImpl =
- '//Sample CRUD Actions for a "Customer" entity' + sLineBreak +
- 'procedure %0:s.GetCustomers;' + sLineBreak +
+ '//Sample CRUD Actions for a "People" entity' + sLineBreak +
+ 'function %0:s.GetPeople: TObjectList;' + sLineBreak +
+ 'var' + sLineBreak +
+ ' lPeople: TObjectList;' + sLineBreak +
'begin' + sLineBreak +
- ' //todo: render a list of customers' + sLineBreak +
+ ' lPeople := TObjectList.Create(True);' + sLineBreak +
+ ' try' + sLineBreak +
+ ' lPeople.Add(TPerson.Create(''Peter'',''Parker'', EncodeDate(1965, 10, 4)));' + sLineBreak +
+ ' lPeople.Add(TPerson.Create(''Bruce'',''Banner'', EncodeDate(1945, 9, 6)));' + sLineBreak +
+ ' lPeople.Add(TPerson.Create(''Reed'',''Richards'', EncodeDate(1955, 3, 7)));' + sLineBreak +
+ ' Result := lPeople;' + sLineBreak +
+ ' except' + sLineBreak +
+ ' lPeople.Free;' + sLineBreak +
+ ' raise;' + sLineBreak +
+ ' end;' + sLineBreak +
'end;' + sLineBreak + sLineBreak +
- 'procedure %0:s.GetCustomer(id: Integer);' + sLineBreak +
+ 'function %0:s.GetPerson(ID: Integer): TPerson;' + sLineBreak +
+ 'var' + sLineBreak +
+ ' lPeople: TObjectList;' + sLineBreak +
'begin' + sLineBreak +
- ' //todo: render the customer by id' + sLineBreak +
+ ' lPeople := GetPeople;' + sLineBreak +
+ ' try' + sLineBreak +
+ ' Result := lPeople.ExtractAt(ID mod lPeople.Count);' + sLineBreak +
+ ' finally' + sLineBreak +
+ ' lPeople.Free;' + sLineBreak +
+ ' end;' + sLineBreak +
'end;' + sLineBreak + sLineBreak +
- 'procedure %0:s.CreateCustomer;' + sLineBreak +
+ 'function %0:s.CreatePerson([MVCFromBody] Person: TPerson): TMVCResponse;' + sLineBreak +
'begin' + sLineBreak +
- ' //todo: create a new customer' + sLineBreak +
+ ' LogI(''Created '' + Person.FirstName + '' '' + Person.LastName);' + sLineBreak +
+ ' Result := TMVCResponse.Create(HTTP_STATUS.Created, ''Person created'');' + sLineBreak +
'end;' + sLineBreak + sLineBreak +
- 'procedure %0:s.UpdateCustomer(id: Integer);' + sLineBreak +
+ 'function %0:s.UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): TMVCResponse;' + sLineBreak +
'begin' + sLineBreak +
- ' //todo: update customer by id' + sLineBreak +
+ ' LogI(''Updated '' + Person.FirstName + '' '' + Person.LastName);' + sLineBreak +
+ ' Result := TMVCResponse.Create(HTTP_STATUS.OK, ''Person updated'');' + sLineBreak +
'end;' + sLineBreak + sLineBreak +
- 'procedure %0:s.DeleteCustomer(id: Integer);' + sLineBreak +
+ 'function %0:s.DeletePerson(ID: Integer): TMVCResponse;' + sLineBreak +
'begin' + sLineBreak +
- ' //todo: delete customer by id' + sLineBreak +
- 'end;' + sLineBreak + sLineBreak;
+ ' LogI(''Deleted person with id '' + ID.ToString);' + sLineBreak +
+ ' Result := TMVCResponse.Create(HTTP_STATUS.OK, ''Person deleted'');' + sLineBreak +
+ 'end;' + sLineBreak;
sActionFiltersIntf =
' protected' + sLineBreak +
@@ -242,6 +269,30 @@ resourcestring
' inherited;' + sLineBreak +
'end;' + sLineBreak;
+ sBOClassesIntf =
+ ' [MVCNameCase(ncCamelCase)]' + sLineBreak +
+ ' TPerson = class' + sLineBreak +
+ ' private' + sLineBreak +
+ ' fFirstName: String;' + sLineBreak +
+ ' fLastName: String;' + sLineBreak +
+ ' fDOB: TDate;' + sLineBreak +
+ ' public' + sLineBreak +
+ ' property FirstName: String read fFirstName write fFirstName;' + sLineBreak +
+ ' property LastName: String read fLastName write fLastName;' + sLineBreak +
+ ' property DOB: TDate read fDOB write fDOB; ' + sLineBreak +
+ ' constructor Create(FirstName, LastName: String; DOB: TDate);' + sLineBreak +
+ ' end;' + sLineBreak;
+
+ sBOClassesImpl =
+ sLineBreak +
+ 'constructor %0:s.Create(FirstName, LastName: String; DOB: TDate);' + sLineBreak +
+ 'begin' + sLineBreak +
+ ' inherited Create;' + sLineBreak +
+ ' fFirstName := FirstName;' + sLineBreak +
+ ' fLastName := LastName;' + sLineBreak +
+ ' fDOB := DOB;' + sLineBreak +
+ 'end;' + sLineBreak;
+
sDefaultControllerName = 'TMyController';
sDefaultWebModuleName = 'TMyWebModule';
sDefaultServerPort = '8080';
diff --git a/ideexpert/DMVC.Expert.ProjectWizardEx.pas b/ideexpert/DMVC.Expert.ProjectWizardEx.pas
index 22153672..42ed4ac1 100644
--- a/ideexpert/DMVC.Expert.ProjectWizardEx.pas
+++ b/ideexpert/DMVC.Expert.ProjectWizardEx.pas
@@ -94,7 +94,7 @@ begin
JSONRPCUnitCreator: IOTACreator;
WebModuleCreator: IOTAModuleCreator;
lProjectSourceCreator: IOTACreator;
- lJSONRPCUnitName: string;
+ lJSONRPCUnitName: string;
begin
WizardForm := TfrmDMVCNewProject.Create(Application);
try
diff --git a/lib/loggerpro/LoggerPro.pas b/lib/loggerpro/LoggerPro.pas
index a03201f1..57ecf29c 100644
--- a/lib/loggerpro/LoggerPro.pas
+++ b/lib/loggerpro/LoggerPro.pas
@@ -358,6 +358,7 @@ function GetDefaultFormatSettings: TFormatSettings;
begin
Result.DateSeparator := '-';
Result.TimeSeparator := ':';
+ Result.DecimalSeparator := '.';
Result.ShortDateFormat := 'YYYY-MM-DD HH:NN:SS:ZZZ';
Result.ShortTimeFormat := 'HH:NN:SS';
end;
diff --git a/lib/swagdoc/Source/SwagDoc.dpk b/lib/swagdoc/Source/SwagDoc.dpk
index 0620b52d..cb1561ab 100644
--- a/lib/swagdoc/Source/SwagDoc.dpk
+++ b/lib/swagdoc/Source/SwagDoc.dpk
@@ -26,6 +26,7 @@ package SwagDoc;
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$DESCRIPTION 'SwagDoc Library'}
+{$LIBSUFFIX '113'}
{$RUNONLY}
{$IMPLICITBUILD OFF}
diff --git a/lib/swagdoc/Source/SwagDoc.dproj b/lib/swagdoc/Source/SwagDoc.dproj
index 3fb504e8..e741e6e6 100644
--- a/lib/swagdoc/Source/SwagDoc.dproj
+++ b/lib/swagdoc/Source/SwagDoc.dproj
@@ -97,6 +97,7 @@
0
1033
CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 113
false
diff --git a/packages/d111/dmvcframeworkDT.dpk b/packages/d111/dmvcframeworkDT.dpk
deleted file mode 100644
index 12457b25..00000000
--- a/packages/d111/dmvcframeworkDT.dpk
+++ /dev/null
@@ -1,58 +0,0 @@
-package dmvcframeworkDT;
-
-{$R *.res}
-{$R *.dres}
-{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
-{$ALIGN 8}
-{$ASSERTIONS ON}
-{$BOOLEVAL OFF}
-{$DEBUGINFO OFF}
-{$EXTENDEDSYNTAX ON}
-{$IMPORTEDDATA ON}
-{$IOCHECKS ON}
-{$LOCALSYMBOLS ON}
-{$LONGSTRINGS ON}
-{$OPENSTRINGS ON}
-{$OPTIMIZATION OFF}
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$REFERENCEINFO ON}
-{$SAFEDIVIDE OFF}
-{$STACKFRAMES ON}
-{$TYPEDADDRESS OFF}
-{$VARSTRINGCHECKS ON}
-{$WRITEABLECONST OFF}
-{$MINENUMSIZE 1}
-{$IMAGEBASE $400000}
-{$DEFINE DEBUG}
-{$ENDIF IMPLICITBUILDING}
-{$DESCRIPTION 'DelphiMVCFramework 3.x - Design Time Support'}
-{$LIBSUFFIX '111'}
-{$IMPLICITBUILD ON}
-
-requires
- rtl,
- designide,
- ExpertsCreators,
- IndySystem,
- IndyProtocols,
- IndyCore,
- dbrtl,
- dmvcframeworkRT;
-
-contains
- DMVC.Expert.CodeGen.NewControllerUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewControllerUnit.pas',
- DMVC.Expert.CodeGen.NewDMVCProject in '..\..\ideexpert\DMVC.Expert.CodeGen.NewDMVCProject.pas',
- DMVC.Expert.CodeGen.NewProject in '..\..\ideexpert\DMVC.Expert.CodeGen.NewProject.pas',
- DMVC.Expert.CodeGen.NewUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewUnit.pas',
- DMVC.Expert.CodeGen.NewWebModuleUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewWebModuleUnit.pas',
- DMVC.Expert.CodeGen.SourceFile in '..\..\ideexpert\DMVC.Expert.CodeGen.SourceFile.pas',
- DMVC.Expert.CodeGen.Templates in '..\..\ideexpert\DMVC.Expert.CodeGen.Templates.pas',
- DMVC.Expert.Forms.NewProjectWizard in '..\..\ideexpert\DMVC.Expert.Forms.NewProjectWizard.pas' {frmDMVCNewProject},
- DMVC.Expert.Forms.NewUnitWizard in '..\..\ideexpert\DMVC.Expert.Forms.NewUnitWizard.pas' {frmDMVCNewUnit},
- DMVC.Expert.NewUnitWizardEx in '..\..\ideexpert\DMVC.Expert.NewUnitWizardEx.pas',
- DMVC.Expert.ProjectWizardEx in '..\..\ideexpert\DMVC.Expert.ProjectWizardEx.pas',
- DMVC.Expert.Registration in '..\..\ideexpert\DMVC.Expert.Registration.pas',
- DMVC.Splash.Registration in '..\..\ideexpert\DMVC.Splash.Registration.pas';
-
-end.
diff --git a/packages/d111/dmvcframeworkRT.dpk b/packages/d111/dmvcframeworkRT.dpk
deleted file mode 100644
index 3f9d64df..00000000
--- a/packages/d111/dmvcframeworkRT.dpk
+++ /dev/null
@@ -1,120 +0,0 @@
-package dmvcframeworkRT;
-
-{$R *.res}
-{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
-{$ALIGN 8}
-{$ASSERTIONS ON}
-{$BOOLEVAL OFF}
-{$DEBUGINFO OFF}
-{$EXTENDEDSYNTAX ON}
-{$IMPORTEDDATA ON}
-{$IOCHECKS ON}
-{$LOCALSYMBOLS ON}
-{$LONGSTRINGS ON}
-{$OPENSTRINGS ON}
-{$OPTIMIZATION OFF}
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$REFERENCEINFO ON}
-{$SAFEDIVIDE OFF}
-{$STACKFRAMES ON}
-{$TYPEDADDRESS OFF}
-{$VARSTRINGCHECKS ON}
-{$WRITEABLECONST OFF}
-{$MINENUMSIZE 1}
-{$IMAGEBASE $400000}
-{$DEFINE DEBUG}
-{$ENDIF IMPLICITBUILDING}
-{$DESCRIPTION 'DMVCFramework - CopyRight (2010-2023) Daniele Teti and the DMVCFramework Team'}
-{$LIBSUFFIX '111'}
-{$RUNONLY}
-{$IMPLICITBUILD ON}
-
-requires
- rtl,
- inet,
- FireDAC,
- IndyCore,
- IndyProtocols,
- FireDACIBDriver,
- FireDACMySQLDriver,
- loggerproRT,
- FireDACPgDriver,
- FireDACSqliteDriver,
- SwagDoc;
-
-contains
- Web.HTTPDImpl,
- Web.ApacheConst,
- Web.ApacheHTTP,
- Web.Win.IsapiHTTP,
- Web.HTTPDMethods,
- MVCFramework in '..\..\sources\MVCFramework.pas',
- MVCFramework.AsyncTask in '..\..\sources\MVCFramework.AsyncTask.pas',
- MVCFramework.Middleware.Swagger in '..\..\sources\MVCFramework.Middleware.Swagger.pas',
- MVCFramework.Middleware.Trace in '..\..\sources\MVCFramework.Middleware.Trace.pas',
- MVCFramework.Middleware.ETag in '..\..\sources\MVCFramework.Middleware.ETag.pas',
- MVCFramework.ActiveRecord in '..\..\sources\MVCFramework.ActiveRecord.pas',
- MVCFramework.ActiveRecordController in '..\..\sources\MVCFramework.ActiveRecordController.pas',
- MVCFramework.ApplicationSession in '..\..\sources\MVCFramework.ApplicationSession.pas',
- MVCFramework.Cache in '..\..\sources\MVCFramework.Cache.pas',
- MVCFramework.Commons in '..\..\sources\MVCFramework.Commons.pas',
- MVCFramework.Console in '..\..\sources\MVCFramework.Console.pas',
- MVCFramework.DataSet.Utils in '..\..\sources\MVCFramework.DataSet.Utils.pas',
- MVCFramework.DuckTyping in '..\..\sources\MVCFramework.DuckTyping.pas',
- MVCFramework.FireDAC.Utils in '..\..\sources\MVCFramework.FireDAC.Utils.pas',
- MVCFramework.HMAC in '..\..\sources\MVCFramework.HMAC.pas',
- MVCFramework.JSONRPC.Client in '..\..\sources\MVCFramework.JSONRPC.Client.pas',
- MVCFramework.JSONRPC in '..\..\sources\MVCFramework.JSONRPC.pas',
- MVCFramework.JWT in '..\..\sources\MVCFramework.JWT.pas',
- MVCFramework.Logger in '..\..\sources\MVCFramework.Logger.pas',
- MVCFramework.Middleware.Analytics in '..\..\sources\MVCFramework.Middleware.Analytics.pas',
- MVCFramework.Middleware.Authentication in '..\..\sources\MVCFramework.Middleware.Authentication.pas',
- MVCFramework.Middleware.Authentication.RoleBasedAuthHandler in '..\..\sources\MVCFramework.Middleware.Authentication.RoleBasedAuthHandler.pas',
- MVCFramework.Middleware.Compression in '..\..\sources\MVCFramework.Middleware.Compression.pas',
- MVCFramework.Middleware.CORS in '..\..\sources\MVCFramework.Middleware.CORS.pas',
- MVCFramework.Middleware.JWT in '..\..\sources\MVCFramework.Middleware.JWT.pas',
- MVCFramework.Middleware.SecurityHeaders in '..\..\sources\MVCFramework.Middleware.SecurityHeaders.pas',
- MVCFramework.MultiMap in '..\..\sources\MVCFramework.MultiMap.pas',
- MVCFramework.Patches in '..\..\sources\MVCFramework.Patches.pas',
- MVCFramework.RESTAdapter in '..\..\sources\MVCFramework.RESTAdapter.pas',
- MVCFramework.Router in '..\..\sources\MVCFramework.Router.pas',
- MVCFramework.RQL.AST2FirebirdSQL in '..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
- MVCFramework.RQL.AST2InterbaseSQL in '..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas',
- MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
- MVCFramework.RQL.AST2PostgreSQL in '..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas',
- MVCFramework.RQL.AST2SQLite in '..\..\sources\MVCFramework.RQL.AST2SQLite.pas',
- MVCFramework.RQL.Parser in '..\..\sources\MVCFramework.RQL.Parser.pas',
- MVCFramework.Rtti.Utils in '..\..\sources\MVCFramework.Rtti.Utils.pas',
- MVCFramework.Serializer.Abstract in '..\..\sources\MVCFramework.Serializer.Abstract.pas',
- MVCFramework.Serializer.Commons in '..\..\sources\MVCFramework.Serializer.Commons.pas',
- MVCFramework.Serializer.Defaults in '..\..\sources\MVCFramework.Serializer.Defaults.pas',
- MVCFramework.Serializer.Intf in '..\..\sources\MVCFramework.Serializer.Intf.pas',
- MVCFramework.Serializer.JsonDataObjects.CustomTypes in '..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas',
- MVCFramework.Serializer.JsonDataObjects in '..\..\sources\MVCFramework.Serializer.JsonDataObjects.pas',
- MVCFramework.Session in '..\..\sources\MVCFramework.Session.pas',
- MVCFramework.SysControllers in '..\..\sources\MVCFramework.SysControllers.pas',
- MVCFramework.SystemJSONUtils in '..\..\sources\MVCFramework.SystemJSONUtils.pas',
- MVCFramework.View.Cache in '..\..\sources\MVCFramework.View.Cache.pas',
- MVCFramework.Controllers.Register in '..\..\sources\MVCFramework.Controllers.Register.pas',
- MVCFramework.SQLGenerators.Firebird in '..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
- MVCFramework.SQLGenerators.Interbase in '..\..\sources\MVCFramework.SQLGenerators.Interbase.pas',
- MVCFramework.SQLGenerators.MySQL in '..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
- MVCFramework.SQLGenerators.PostgreSQL in '..\..\sources\MVCFramework.SQLGenerators.PostgreSQL.pas',
- MVCFramework.SQLGenerators.Sqlite in '..\..\sources\MVCFramework.SQLGenerators.Sqlite.pas',
- MVCFramework.Swagger.Commons in '..\..\sources\MVCFramework.Swagger.Commons.pas',
- MVCFramework.Nullables in '..\..\sources\MVCFramework.Nullables.pas',
- MVCFramework.Serializer.HTML in '..\..\sources\MVCFramework.Serializer.HTML.pas',
- MVCFramework.LRUCache in '..\..\sources\MVCFramework.LRUCache.pas',
- MVCFramework.RESTClient.Commons in '..\..\sources\MVCFramework.RESTClient.Commons.pas',
- MVCFramework.RESTClient.Indy in '..\..\sources\MVCFramework.RESTClient.Indy.pas',
- MVCFramework.RESTClient.Intf in '..\..\sources\MVCFramework.RESTClient.Intf.pas',
- MVCFramework.RESTClient in '..\..\sources\MVCFramework.RESTClient.pas',
- MVCFramework.Utils in '..\..\sources\MVCFramework.Utils.pas',
- JsonDataObjects in '..\..\sources\JsonDataObjects.pas';
-
-end.
-
-
-
-
diff --git a/packages/d111/dmvcframework_group.groupproj b/packages/d111/dmvcframework_group.groupproj
deleted file mode 100644
index 7349df03..00000000
--- a/packages/d111/dmvcframework_group.groupproj
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
- {EA879EE4-1245-4456-AED9-57FDF63577E6}
-
-
-
-
-
-
-
-
-
- ..\..\lib\loggerpro\packages\d111\loggerproRT.dproj
-
-
- dmvcframeworkRT.dproj
-
-
-
- Default.Personality.12
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/d112/dmvcframeworkDT.dpk b/packages/d112/dmvcframeworkDT.dpk
deleted file mode 100644
index 6fd2dc2e..00000000
--- a/packages/d112/dmvcframeworkDT.dpk
+++ /dev/null
@@ -1,58 +0,0 @@
-package dmvcframeworkDT;
-
-{$R *.res}
-{$R *.dres}
-{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
-{$ALIGN 8}
-{$ASSERTIONS ON}
-{$BOOLEVAL OFF}
-{$DEBUGINFO OFF}
-{$EXTENDEDSYNTAX ON}
-{$IMPORTEDDATA ON}
-{$IOCHECKS ON}
-{$LOCALSYMBOLS ON}
-{$LONGSTRINGS ON}
-{$OPENSTRINGS ON}
-{$OPTIMIZATION OFF}
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$REFERENCEINFO ON}
-{$SAFEDIVIDE OFF}
-{$STACKFRAMES ON}
-{$TYPEDADDRESS OFF}
-{$VARSTRINGCHECKS ON}
-{$WRITEABLECONST OFF}
-{$MINENUMSIZE 1}
-{$IMAGEBASE $400000}
-{$DEFINE DEBUG}
-{$ENDIF IMPLICITBUILDING}
-{$DESCRIPTION 'DelphiMVCFramework 3.x - Design Time Support'}
-{$LIBSUFFIX '112'}
-{$IMPLICITBUILD ON}
-
-requires
- rtl,
- designide,
- ExpertsCreators,
- IndySystem,
- IndyProtocols,
- IndyCore,
- dbrtl,
- dmvcframeworkRT;
-
-contains
- DMVC.Expert.CodeGen.NewControllerUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewControllerUnit.pas',
- DMVC.Expert.CodeGen.NewDMVCProject in '..\..\ideexpert\DMVC.Expert.CodeGen.NewDMVCProject.pas',
- DMVC.Expert.CodeGen.NewProject in '..\..\ideexpert\DMVC.Expert.CodeGen.NewProject.pas',
- DMVC.Expert.CodeGen.NewUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewUnit.pas',
- DMVC.Expert.CodeGen.NewWebModuleUnit in '..\..\ideexpert\DMVC.Expert.CodeGen.NewWebModuleUnit.pas',
- DMVC.Expert.CodeGen.SourceFile in '..\..\ideexpert\DMVC.Expert.CodeGen.SourceFile.pas',
- DMVC.Expert.CodeGen.Templates in '..\..\ideexpert\DMVC.Expert.CodeGen.Templates.pas',
- DMVC.Expert.Forms.NewProjectWizard in '..\..\ideexpert\DMVC.Expert.Forms.NewProjectWizard.pas' {frmDMVCNewProject},
- DMVC.Expert.Forms.NewUnitWizard in '..\..\ideexpert\DMVC.Expert.Forms.NewUnitWizard.pas' {frmDMVCNewUnit},
- DMVC.Expert.NewUnitWizardEx in '..\..\ideexpert\DMVC.Expert.NewUnitWizardEx.pas',
- DMVC.Expert.ProjectWizardEx in '..\..\ideexpert\DMVC.Expert.ProjectWizardEx.pas',
- DMVC.Expert.Registration in '..\..\ideexpert\DMVC.Expert.Registration.pas',
- DMVC.Splash.Registration in '..\..\ideexpert\DMVC.Splash.Registration.pas';
-
-end.
diff --git a/packages/d112/dmvcframeworkRT.dpk b/packages/d112/dmvcframeworkRT.dpk
deleted file mode 100644
index 49a16eef..00000000
--- a/packages/d112/dmvcframeworkRT.dpk
+++ /dev/null
@@ -1,120 +0,0 @@
-package dmvcframeworkRT;
-
-{$R *.res}
-{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
-{$ALIGN 8}
-{$ASSERTIONS ON}
-{$BOOLEVAL OFF}
-{$DEBUGINFO OFF}
-{$EXTENDEDSYNTAX ON}
-{$IMPORTEDDATA ON}
-{$IOCHECKS ON}
-{$LOCALSYMBOLS ON}
-{$LONGSTRINGS ON}
-{$OPENSTRINGS ON}
-{$OPTIMIZATION OFF}
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$REFERENCEINFO ON}
-{$SAFEDIVIDE OFF}
-{$STACKFRAMES ON}
-{$TYPEDADDRESS OFF}
-{$VARSTRINGCHECKS ON}
-{$WRITEABLECONST OFF}
-{$MINENUMSIZE 1}
-{$IMAGEBASE $400000}
-{$DEFINE DEBUG}
-{$ENDIF IMPLICITBUILDING}
-{$DESCRIPTION 'DMVCFramework - CopyRight (2010-2023) Daniele Teti and the DMVCFramework Team'}
-{$LIBSUFFIX '112'}
-{$RUNONLY}
-{$IMPLICITBUILD ON}
-
-requires
- rtl,
- inet,
- FireDAC,
- IndyCore,
- IndyProtocols,
- FireDACIBDriver,
- FireDACMySQLDriver,
- loggerproRT,
- FireDACPgDriver,
- FireDACSqliteDriver,
- SwagDoc;
-
-contains
- Web.HTTPDImpl,
- Web.ApacheConst,
- Web.ApacheHTTP,
- Web.Win.IsapiHTTP,
- Web.HTTPDMethods,
- MVCFramework in '..\..\sources\MVCFramework.pas',
- MVCFramework.AsyncTask in '..\..\sources\MVCFramework.AsyncTask.pas',
- MVCFramework.Middleware.Swagger in '..\..\sources\MVCFramework.Middleware.Swagger.pas',
- MVCFramework.Middleware.Trace in '..\..\sources\MVCFramework.Middleware.Trace.pas',
- MVCFramework.Middleware.ETag in '..\..\sources\MVCFramework.Middleware.ETag.pas',
- MVCFramework.ActiveRecord in '..\..\sources\MVCFramework.ActiveRecord.pas',
- MVCFramework.ActiveRecordController in '..\..\sources\MVCFramework.ActiveRecordController.pas',
- MVCFramework.ApplicationSession in '..\..\sources\MVCFramework.ApplicationSession.pas',
- MVCFramework.Cache in '..\..\sources\MVCFramework.Cache.pas',
- MVCFramework.Commons in '..\..\sources\MVCFramework.Commons.pas',
- MVCFramework.Console in '..\..\sources\MVCFramework.Console.pas',
- MVCFramework.DataSet.Utils in '..\..\sources\MVCFramework.DataSet.Utils.pas',
- MVCFramework.DuckTyping in '..\..\sources\MVCFramework.DuckTyping.pas',
- MVCFramework.FireDAC.Utils in '..\..\sources\MVCFramework.FireDAC.Utils.pas',
- MVCFramework.HMAC in '..\..\sources\MVCFramework.HMAC.pas',
- MVCFramework.JSONRPC.Client in '..\..\sources\MVCFramework.JSONRPC.Client.pas',
- MVCFramework.JSONRPC in '..\..\sources\MVCFramework.JSONRPC.pas',
- MVCFramework.JWT in '..\..\sources\MVCFramework.JWT.pas',
- MVCFramework.Logger in '..\..\sources\MVCFramework.Logger.pas',
- MVCFramework.Middleware.Analytics in '..\..\sources\MVCFramework.Middleware.Analytics.pas',
- MVCFramework.Middleware.Authentication in '..\..\sources\MVCFramework.Middleware.Authentication.pas',
- MVCFramework.Middleware.Authentication.RoleBasedAuthHandler in '..\..\sources\MVCFramework.Middleware.Authentication.RoleBasedAuthHandler.pas',
- MVCFramework.Middleware.Compression in '..\..\sources\MVCFramework.Middleware.Compression.pas',
- MVCFramework.Middleware.CORS in '..\..\sources\MVCFramework.Middleware.CORS.pas',
- MVCFramework.Middleware.JWT in '..\..\sources\MVCFramework.Middleware.JWT.pas',
- MVCFramework.Middleware.SecurityHeaders in '..\..\sources\MVCFramework.Middleware.SecurityHeaders.pas',
- MVCFramework.MultiMap in '..\..\sources\MVCFramework.MultiMap.pas',
- MVCFramework.Patches in '..\..\sources\MVCFramework.Patches.pas',
- MVCFramework.RESTAdapter in '..\..\sources\MVCFramework.RESTAdapter.pas',
- MVCFramework.Router in '..\..\sources\MVCFramework.Router.pas',
- MVCFramework.RQL.AST2FirebirdSQL in '..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
- MVCFramework.RQL.AST2InterbaseSQL in '..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas',
- MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
- MVCFramework.RQL.AST2PostgreSQL in '..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas',
- MVCFramework.RQL.AST2SQLite in '..\..\sources\MVCFramework.RQL.AST2SQLite.pas',
- MVCFramework.RQL.Parser in '..\..\sources\MVCFramework.RQL.Parser.pas',
- MVCFramework.Rtti.Utils in '..\..\sources\MVCFramework.Rtti.Utils.pas',
- MVCFramework.Serializer.Abstract in '..\..\sources\MVCFramework.Serializer.Abstract.pas',
- MVCFramework.Serializer.Commons in '..\..\sources\MVCFramework.Serializer.Commons.pas',
- MVCFramework.Serializer.Defaults in '..\..\sources\MVCFramework.Serializer.Defaults.pas',
- MVCFramework.Serializer.Intf in '..\..\sources\MVCFramework.Serializer.Intf.pas',
- MVCFramework.Serializer.JsonDataObjects.CustomTypes in '..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas',
- MVCFramework.Serializer.JsonDataObjects in '..\..\sources\MVCFramework.Serializer.JsonDataObjects.pas',
- MVCFramework.Session in '..\..\sources\MVCFramework.Session.pas',
- MVCFramework.SysControllers in '..\..\sources\MVCFramework.SysControllers.pas',
- MVCFramework.SystemJSONUtils in '..\..\sources\MVCFramework.SystemJSONUtils.pas',
- MVCFramework.View.Cache in '..\..\sources\MVCFramework.View.Cache.pas',
- MVCFramework.Controllers.Register in '..\..\sources\MVCFramework.Controllers.Register.pas',
- MVCFramework.SQLGenerators.Firebird in '..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
- MVCFramework.SQLGenerators.Interbase in '..\..\sources\MVCFramework.SQLGenerators.Interbase.pas',
- MVCFramework.SQLGenerators.MySQL in '..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
- MVCFramework.SQLGenerators.PostgreSQL in '..\..\sources\MVCFramework.SQLGenerators.PostgreSQL.pas',
- MVCFramework.SQLGenerators.Sqlite in '..\..\sources\MVCFramework.SQLGenerators.Sqlite.pas',
- MVCFramework.Swagger.Commons in '..\..\sources\MVCFramework.Swagger.Commons.pas',
- MVCFramework.Nullables in '..\..\sources\MVCFramework.Nullables.pas',
- MVCFramework.Serializer.HTML in '..\..\sources\MVCFramework.Serializer.HTML.pas',
- MVCFramework.LRUCache in '..\..\sources\MVCFramework.LRUCache.pas',
- MVCFramework.RESTClient.Commons in '..\..\sources\MVCFramework.RESTClient.Commons.pas',
- MVCFramework.RESTClient.Indy in '..\..\sources\MVCFramework.RESTClient.Indy.pas',
- MVCFramework.RESTClient.Intf in '..\..\sources\MVCFramework.RESTClient.Intf.pas',
- MVCFramework.RESTClient in '..\..\sources\MVCFramework.RESTClient.pas',
- MVCFramework.Utils in '..\..\sources\MVCFramework.Utils.pas',
- JsonDataObjects in '..\..\sources\JsonDataObjects.pas';
-
-end.
-
-
-
-
diff --git a/packages/d112/dmvcframework_group.groupproj b/packages/d112/dmvcframework_group.groupproj
deleted file mode 100644
index 7349df03..00000000
--- a/packages/d112/dmvcframework_group.groupproj
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
- {EA879EE4-1245-4456-AED9-57FDF63577E6}
-
-
-
-
-
-
-
-
-
- ..\..\lib\loggerpro\packages\d111\loggerproRT.dproj
-
-
- dmvcframeworkRT.dproj
-
-
-
- Default.Personality.12
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ISAPI/ISAPI/isapiapp.dpr b/samples/ISAPI/ISAPI/isapiapp.dpr
index 9352efa0..5af55ee6 100644
--- a/samples/ISAPI/ISAPI/isapiapp.dpr
+++ b/samples/ISAPI/ISAPI/isapiapp.dpr
@@ -1,22 +1,28 @@
library isapiapp;
-
-
-
-
uses
Winapi.ActiveX,
System.Win.ComObj,
+ MVCFramework.DotEnv,
+ MVCFramework.Commons,
+ MVCFramework.Logger,
Web.WebBroker,
Web.Win.ISAPIApp,
Web.Win.ISAPIThreadPool,
MainDataModuleUnit in '..\..\WineCellarSample\winecellarserver\MainDataModuleUnit.pas' {WineCellarDataModule: TDataModule},
MainWebModuleUnit in '..\..\WineCellarSample\winecellarserver\MainWebModuleUnit.pas' {wm: TWebModule},
WinesBO in '..\..\WineCellarSample\winecellarserver\WinesBO.pas',
- WineCellarAppControllerU in '..\..\WineCellarSample\winecellarserver\WineCellarAppControllerU.pas';
+ WineCellarAppControllerU in '..\..\WineCellarSample\winecellarserver\WineCellarAppControllerU.pas',
+ Winapi.Windows;
{$R *.res}
+function TerminateExtension(dwFlags: DWORD): BOOL; stdcall;
+begin
+ ReleaseGlobalLogger;
+ Result := Web.Win.ISAPIThreadPool.TerminateExtension(dwFlags);
+end;
+
exports
GetExtensionVersion,
HttpExtensionProc,
@@ -26,5 +32,19 @@ begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
Application.WebModuleClass := WebModuleClass;
+ dotEnvConfigure(
+ function: IMVCDotEnv
+ begin
+ Result := NewDotEnv
+ .WithStrategy(TMVCDotEnvPriority.FileThenEnv)
+ //if available, by default, loads default environment (.env)
+ .UseProfile('test') //if available loads the test environment (.env.test)
+ .UseProfile('prod') //if available loads the prod environment (.env.prod)
+ .UseLogger(procedure(LogItem: String)
+ begin
+ LogW('dotEnv: ' + LogItem);
+ end)
+ .Build(); //uses the executable folder to look for .env* files
+ end);
Application.Run;
end.
diff --git a/samples/ISAPI/ISAPI/isapiapp.dproj b/samples/ISAPI/ISAPI/isapiapp.dproj
index aa952676..68a11e56 100644
--- a/samples/ISAPI/ISAPI/isapiapp.dproj
+++ b/samples/ISAPI/ISAPI/isapiapp.dproj
@@ -6,8 +6,8 @@
isapiapp.dpr
True
Debug
- Win32
- 1
+ Win64
+ 2
Library
@@ -34,6 +34,12 @@
true
true
+
+ true
+ Cfg_1
+ true
+ true
+
true
Base
@@ -66,6 +72,14 @@
FireDACSqliteDriver;DBXSqliteDriver;FireDACPgDriver;fmx;TreeViewPresenter;IndySystem;TeeDB;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;inetdbxpress;FireDACDb2Driver;adortl;DataBindingsVCL;FireDACASADriver;bindcompfmx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DataBindings;DBXOdbcDriver;vclFireDAC;xmlrtl;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;fmxinfopower;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;VirtualTreesR;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ ..\bin
+ (None)
+ none
DEBUG;$(DCC_Define)
@@ -82,6 +96,15 @@
1033
false
+
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ (None)
+ none
+ C:\Windows\System32\inetsrv\w3wp.exe
+ -debug
+
false
RELEASE;$(DCC_Define)
@@ -94,12 +117,10 @@
- dfm
TDataModule
- dfm
TWebModule
@@ -175,10 +196,10 @@
- Embarcadero C++Builder Office 2000 Servers Package
- Embarcadero C++Builder Office XP Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
@@ -579,6 +600,127 @@
0
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
@@ -779,127 +921,6 @@
1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
@@ -914,8 +935,8 @@
- True
- False
+ False
+ True
12
diff --git a/samples/ISAPI/ProjectGroup.groupproj b/samples/ISAPI/ProjectGroup.groupproj
new file mode 100644
index 00000000..91db9ac1
--- /dev/null
+++ b/samples/ISAPI/ProjectGroup.groupproj
@@ -0,0 +1,48 @@
+
+
+ {5EA2FE29-4523-4296-8CFA-94B6AC904435}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ISAPI/StandAlone/ConsoleApp.dpr b/samples/ISAPI/StandAlone/ConsoleApp.dpr
new file mode 100644
index 00000000..561ffb2f
--- /dev/null
+++ b/samples/ISAPI/StandAlone/ConsoleApp.dpr
@@ -0,0 +1,65 @@
+program ConsoleApp;
+{$APPTYPE CONSOLE}
+
+
+uses
+ MVCFramework,
+ MVCFramework.Commons,
+ MVCFramework.Signal,
+ MVCFramework.DotEnv,
+ MVCFramework.Logger,
+ System.SysUtils,
+ Winapi.Windows,
+ IdHTTPWebBrokerBridge,
+ Web.WebReq,
+ Web.WebBroker,
+ WinesBO in '..\..\WineCellarSample\winecellarserver\WinesBO.pas',
+ WineCellarAppControllerU in '..\..\WineCellarSample\winecellarserver\WineCellarAppControllerU.pas',
+ MainWebModuleUnit in '..\..\WineCellarSample\winecellarserver\MainWebModuleUnit.pas' {wm: TWebModule},
+ MainDataModuleUnit in '..\..\WineCellarSample\winecellarserver\MainDataModuleUnit.pas' {WineCellarDataModule: TDataModule};
+
+{$R *.res}
+
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln(Format('Starting HTTP Server or port %d', [APort]));
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.DefaultPort := APort;
+ LServer.Active := True;
+ Write('CTRL+C to stop the server');
+ WaitForTerminationSignal;
+ EnterInShutdownState;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+ dotEnvConfigure(
+ function: IMVCDotEnv
+ begin
+ Result := NewDotEnv
+ .WithStrategy(TMVCDotEnvPriority.FileThenEnv)
+ //if available, by default, loads default environment (.env)
+ .UseProfile('test') //if available loads the test environment (.env.test)
+ .UseProfile('prod') //if available loads the prod environment (.env.prod)
+ .UseLogger(procedure(LogItem: String)
+ begin
+ LogW('dotEnv: ' + LogItem);
+ end)
+ .Build(); //uses the executable folder to look for .env* files
+ end);
+ RunServer(8080);
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end
+
+end.
diff --git a/samples/ISAPI/StandAlone/StandAloneServer.dproj b/samples/ISAPI/StandAlone/ConsoleApp.dproj
similarity index 79%
rename from samples/ISAPI/StandAlone/StandAloneServer.dproj
rename to samples/ISAPI/StandAlone/ConsoleApp.dproj
index 52a2c519..3de05e42 100644
--- a/samples/ISAPI/StandAlone/StandAloneServer.dproj
+++ b/samples/ISAPI/StandAlone/ConsoleApp.dproj
@@ -1,1027 +1,980 @@
-
-
- {89FED123-CDD0-460A-9CC6-5810B281BF84}
- 18.8
- VCL
- StandAloneServer.dpr
- True
- Debug
- Win32
- 1
- Console
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- StandAloneServer
- CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
- $(BDS)\bin\delphi_PROJECTICON.ico
- 1040
- ..\..\..\sources;..\..\..\lib\delphistompclient;..\..\..\lib\loggerpro;..\..\..\lib\dmustache;$(DCC_UnitSearchPath)
- $(BDS)\bin\delphi_PROJECTICNS.icns
- System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
-
-
- true
- Base
- true
- true
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- true
- true
- true
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- true
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- true
- true
- Debug
- true
-
-
- true
- Base
- true
- Debug
-
-
- None
- ..\bin
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- 1033
- FireDACSqliteDriver;TsiLang_XE5r;DBXSqliteDriver;FireDACPgDriver;fmx;TreeViewPresenter;IndySystem;i18n;TeeDB;frx19;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DPFAndroidPackagesXE5;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;i18nDB;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;CodeSiteExpressPkg;DataSnapFireDAC;FireDACDBXDriver;inetdbxpress;FireDACDb2Driver;adortl;CustomAdaptersMDPackage;DataBindingsVCL;FireDACASADriver;bindcompfmx;vcldbx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DataBindings;DBXOdbcDriver;vclFireDAC;CPortLibDXE;xmlrtl;svnui;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;fmxinfopower;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;bdertl;VirtualTreesR;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)
- CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName)
-
-
- FireDACSqliteDriver;DBXSqliteDriver;FireDACPgDriver;fmx;TreeViewPresenter;IndySystem;TeeDB;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;inetdbxpress;FireDACDb2Driver;adortl;DataBindingsVCL;FireDACASADriver;bindcompfmx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DataBindings;DBXOdbcDriver;vclFireDAC;xmlrtl;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;fmxinfopower;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;VirtualTreesR;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
- 1033
- false
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
-
- MainSource
-
-
-
- dfm
- TWebModule
-
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
-
-
-
-
- False
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- False
- 1040
- 1252
-
-
-
-
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Embarcadero C++Builder Office 2000 Servers Package
- Embarcadero C++Builder Office XP Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
-
-
-
-
-
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- 1
- .framework
-
-
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
- False
- True
- False
-
-
- 12
-
-
-
-
-
+
+
+ {89FED123-CDD0-460A-9CC6-5810B281BF84}
+ 19.5
+ VCL
+ ConsoleApp.dpr
+ True
+ Debug
+ Win64
+ 2
+ Console
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ ConsoleApp
+ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ 1040
+ ..\..\..\sources;..\..\..\lib\delphistompclient;..\..\..\lib\loggerpro;..\..\..\lib\dmustache;$(DCC_UnitSearchPath)
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ Base
+ true
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ true
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ true
+ true
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+
+
+ None
+ ..\bin
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ 1033
+ FireDACSqliteDriver;TsiLang_XE5r;DBXSqliteDriver;FireDACPgDriver;fmx;TreeViewPresenter;IndySystem;i18n;TeeDB;frx19;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DPFAndroidPackagesXE5;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;i18nDB;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;CodeSiteExpressPkg;DataSnapFireDAC;FireDACDBXDriver;inetdbxpress;FireDACDb2Driver;adortl;CustomAdaptersMDPackage;DataBindingsVCL;FireDACASADriver;bindcompfmx;vcldbx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DataBindings;DBXOdbcDriver;vclFireDAC;CPortLibDXE;xmlrtl;svnui;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;fmxinfopower;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;bdertl;VirtualTreesR;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)
+ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName)
+
+
+ FireDACSqliteDriver;DBXSqliteDriver;FireDACPgDriver;fmx;TreeViewPresenter;IndySystem;TeeDB;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;IndyIPCommon;CloudService;DBXMSSQLDriver;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;inetdbxpress;FireDACDb2Driver;adortl;DataBindingsVCL;FireDACASADriver;bindcompfmx;FireDACODBCDriver;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DataBindings;DBXOdbcDriver;vclFireDAC;xmlrtl;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindengine;vclactnband;soaprtl;bindcompdbx;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;fmxinfopower;VclSmp;FireDACMSSQLDriver;FireDAC;VCLRESTComponents;Intraweb;DBXInformixDriver;DataSnapConnectors;FireDACDataSnapDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;VirtualTreesR;FireDACMSAccDriver;DataSnapIndy10ServerTransport;dbexpress;IndyIPClient;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ ..\bin
+ (None)
+ none
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
+ 1033
+ false
+
+
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ none
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+
+
+ dfm
+ TWebModule
+
+
+
+ dfm
+ TDataModule
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ False
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1040
+ 1252
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ConsoleApp.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+
+
+ ConsoleApp.exe
+ true
+
+
+
+
+ ConsoleApp.rsm
+ true
+
+
+
+
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 64
+
+
+ classes
+ 64
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ 1
+ .framework
+
+
+ 1
+ .framework
+
+
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ False
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/samples/ISAPI/StandAlone/StandAloneServer.dpr b/samples/ISAPI/StandAlone/StandAloneServer.dpr
deleted file mode 100644
index 4477d09f..00000000
--- a/samples/ISAPI/StandAlone/StandAloneServer.dpr
+++ /dev/null
@@ -1,55 +0,0 @@
-program StandAloneServer;
-{$APPTYPE CONSOLE}
-
-
-uses
- System.SysUtils,
- Winapi.Windows,
- IdHTTPWebBrokerBridge,
- Web.WebReq,
- Web.WebBroker,
- WebModuleU in '..\WebModules\WebModuleU.pas' {WebModule1: TWebModule} ,
- RoutingSampleControllerU in '..\Controllers\RoutingSampleControllerU.pas',
- BusinessObjectsU in '..\BO\BusinessObjectsU.pas';
-
-{$R *.res}
-
-
-procedure RunServer(APort: Integer);
-var
- LInputRecord: TInputRecord;
- LEvent: DWord;
- LHandle: THandle;
- LServer: TIdHTTPWebBrokerBridge;
-begin
- Writeln(Format('Starting HTTP Server or port %d', [APort]));
- LServer := TIdHTTPWebBrokerBridge.Create(nil);
- try
- LServer.DefaultPort := APort;
- LServer.Active := True;
- Writeln('Press ESC to stop the server');
- LHandle := GetStdHandle(STD_INPUT_HANDLE);
- while True do
- begin
- Win32Check(ReadConsoleInput(LHandle, LInputRecord, 1, LEvent));
- if (LInputRecord.EventType = KEY_EVENT) and
- LInputRecord.Event.KeyEvent.bKeyDown and
- (LInputRecord.Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE) then
- break;
- end;
- finally
- LServer.Free;
- end;
-end;
-
-begin
- try
- if WebRequestHandler <> nil then
- WebRequestHandler.WebModuleClass := WebModuleClass;
- RunServer(8080);
- except
- on E: Exception do
- Writeln(E.ClassName, ': ', E.Message);
- end
-
-end.
diff --git a/samples/ISAPI/bin/.env b/samples/ISAPI/bin/.env
new file mode 100644
index 00000000..5d07214b
--- /dev/null
+++ b/samples/ISAPI/bin/.env
@@ -0,0 +1 @@
+database.path = C:\DEV\dmvcframework\samples\WineCellarSample\winecellarserver\WINES_FB30.FDB
\ No newline at end of file
diff --git a/samples/ISAPI/bin/web.config b/samples/ISAPI/bin/web.config
new file mode 100644
index 00000000..d08c7ca0
--- /dev/null
+++ b/samples/ISAPI/bin/web.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/activerecord_showcase/EntitiesU.pas b/samples/activerecord_showcase/EntitiesU.pas
index 59c8bdd2..7750bd1d 100644
--- a/samples/activerecord_showcase/EntitiesU.pas
+++ b/samples/activerecord_showcase/EntitiesU.pas
@@ -105,6 +105,12 @@ type
[MVCNameCase(ncLowerCase)]
[MVCTable('customers')]
+ [MVCNamedSQLQuery('RatingLessThanPar', 'select * from customers where rating < ? order by code, city desc')]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*firebird*/ * from customers where rating = ? order by code, city desc', TMVCActiveRecordBackEnd.FirebirdSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*postgres*/ * from customers where rating = ? order by code, city desc', TMVCActiveRecordBackEnd.PostgreSQL)]
+ [MVCNamedSQLQuery('RatingEqualsToPar', 'select /*all*/ * from customers where rating = ? order by code, city desc')]
+ [MVCNamedRQLQuery('RatingLessThanPar', 'lt(rating,%d);sort(+code,-city)')]
+ [MVCNamedRQLQuery('RatingEqualsToPar', 'eq(rating,%d);sort(+code,-city)')]
TCustomer = class(TCustomEntity)
private
{$IFNDEF USE_SEQUENCES}
@@ -406,6 +412,35 @@ type
property Orders: TObjectList read GetOrders;
end;
+ [MVCNameCase(ncLowerCase)]
+ [MVCEntityActions([eaRetrieve])]
+ [MVCNamedSQLQuery('CustomersInTheSameCity',
+ 'SELECT c.id, c.DESCRIPTION, c.city, c.code, c.rating, (SELECT count(*) - 1 FROM customers c2 WHERE c2.CITY = c.CITY) customers_in_the_same_city ' +
+ 'FROM CUSTOMERS c WHERE city IS NOT NULL AND city <> '''' ORDER BY customers_in_the_same_city')]
+ TCustomerStats = class(TCustomEntity)
+ private
+ [MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
+ fID: NullableInt64;
+ [MVCTableField('code')]
+ fCode: NullableString;
+ [MVCTableField('description')]
+ fCompanyName: NullableString;
+ [MVCTableField('city')]
+ fCity: string;
+ [MVCTableField('rating')]
+ fRating: NullableInt32;
+ [MVCTableField('customers_in_the_same_city')]
+ fCustomersInTheSameCity: Int32;
+ public
+ property ID: NullableInt64 read fID write fID;
+ property Code: NullableString read fCode write fCode;
+ property CompanyName: NullableString read fCompanyName write fCompanyName;
+ property City: string read fCity write fCity;
+ property Rating: NullableInt32 read fRating write fRating;
+ property CustomersInTheSameCity: Int32 read fCustomersInTheSameCity write fCustomersInTheSameCity;
+ end;
+
+
[MVCNameCase(ncLowerCase)]
[MVCTable('customers')]
TCustomerWithLogic = class(TCustomer)
diff --git a/samples/activerecord_showcase/MainFormU.dfm b/samples/activerecord_showcase/MainFormU.dfm
index 5a2196ec..9b914f49 100644
--- a/samples/activerecord_showcase/MainFormU.dfm
+++ b/samples/activerecord_showcase/MainFormU.dfm
@@ -2,62 +2,49 @@ object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'TMVCActiveRecord - ShowCase'
- ClientHeight = 1423
- ClientWidth = 2760
+ ClientHeight = 569
+ ClientWidth = 1104
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
- Font.Height = -28
+ Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OnDestroy = FormDestroy
OnShow = FormShow
- PixelsPerInch = 240
DesignSize = (
- 2760
- 1423)
- TextHeight = 34
+ 1104
+ 569)
+ TextHeight = 13
object btnCRUD: TButton
- Left = 20
- Top = 20
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 8
+ Width = 121
+ Height = 33
Caption = 'CRUD'
TabOrder = 0
OnClick = btnCRUDClick
end
object btnSelect: TButton
- Left = 20
- Top = 605
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 242
+ Width = 121
+ Height = 33
Caption = 'Queries'
TabOrder = 1
OnClick = btnSelectClick
end
object Memo1: TMemo
- Left = 700
- Top = 20
- Width = 2040
- Height = 1383
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 280
+ Top = 8
+ Width = 816
+ Height = 553
Anchors = [akLeft, akTop, akRight, akBottom]
Ctl3D = True
DoubleBuffered = True
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
- Font.Height = -33
+ Font.Height = -13
Font.Name = 'Consolas'
Font.Style = []
ParentCtl3D = False
@@ -68,310 +55,236 @@ object MainForm: TMainForm
TabOrder = 2
WantReturns = False
WordWrap = False
- ExplicitWidth = 2020
- ExplicitHeight = 1381
+ ExplicitWidth = 812
+ ExplicitHeight = 552
end
object btnRelations: TButton
- Left = 20
- Top = 703
- Width = 303
- Height = 87
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 281
+ Width = 121
+ Height = 35
Caption = 'Relations'
TabOrder = 3
OnClick = btnRelationsClick
end
object btnInheritance: TButton
- Left = 20
- Top = 805
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 322
+ Width = 121
+ Height = 34
Caption = 'Inheritance'
TabOrder = 4
OnClick = btnInheritanceClick
end
object btnValidation: TButton
- Left = 20
- Top = 905
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 362
+ Width = 121
+ Height = 34
Caption = 'Validation'
TabOrder = 5
OnClick = btnValidationClick
end
object btnMultiThreading: TButton
- Left = 360
- Top = 20
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 8
+ Width = 121
+ Height = 33
Caption = 'Multi Threading'
TabOrder = 6
OnClick = btnMultiThreadingClick
end
object btnRQL: TButton
- Left = 20
- Top = 1005
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 402
+ Width = 121
+ Height = 34
Caption = 'RQL Query'
TabOrder = 7
OnClick = btnRQLClick
end
object btnReadOnlyFields: TButton
- Left = 20
- Top = 508
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 203
+ Width = 121
+ Height = 33
Caption = 'CRUD With R/O Field'
TabOrder = 8
OnClick = btnReadOnlyFieldsClick
end
object btnNullTest: TButton
- Left = 360
- Top = 118
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 47
+ Width = 121
+ Height = 33
Caption = 'Nullables'
TabOrder = 9
OnClick = btnNullTestClick
end
object btnCRUDNoAutoInc: TButton
- Left = 20
- Top = 215
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 86
+ Width = 121
+ Height = 33
Caption = 'CRUD (no autoinc)'
TabOrder = 10
OnClick = btnCRUDNoAutoIncClick
end
object btnCRUDWithStringPKs: TButton
- Left = 20
- Top = 313
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 125
+ Width = 121
+ Height = 33
Caption = 'CRUD (string pks)'
TabOrder = 11
OnClick = btnCRUDWithStringPKsClick
end
object btnWithSpaces: TButton
- Left = 20
- Top = 410
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 164
+ Width = 121
+ Height = 33
Caption = 'CRUD (entity with spaces)'
TabOrder = 12
WordWrap = True
OnClick = btnWithSpacesClick
end
object btnCountWithRQL: TButton
- Left = 360
- Top = 215
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 86
+ Width = 121
+ Height = 33
Caption = 'Count with RQL'
TabOrder = 13
OnClick = btnCountWithRQLClick
end
object btnReadAndWriteOnly: TButton
- Left = 360
- Top = 313
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 125
+ Width = 121
+ Height = 33
Caption = 'R/O, R/W'
TabOrder = 14
OnClick = btnReadAndWriteOnlyClick
end
object btnClientGeneratedPK: TButton
- Left = 360
- Top = 410
- Width = 303
- Height = 83
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 164
+ Width = 121
+ Height = 33
Caption = 'Client Generated PKs'
TabOrder = 15
OnClick = btnClientGeneratedPKClick
end
object btnAttributes: TButton
- Left = 360
- Top = 508
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 203
+ Width = 121
+ Height = 33
Caption = 'Attributes'
TabOrder = 16
OnClick = btnAttributesClick
end
object btnJSON_XML_Types: TButton
- Left = 360
- Top = 605
- Width = 303
- Height = 88
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 242
+ Width = 121
+ Height = 35
Caption = 'JSON && XML'
TabOrder = 17
OnClick = btnJSON_XML_TypesClick
end
object btnMerge: TButton
- Left = 360
- Top = 708
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 283
+ Width = 121
+ Height = 34
Caption = 'Merge'
TabOrder = 18
OnClick = btnMergeClick
end
object btnTableFilter: TButton
- Left = 360
- Top = 808
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 323
+ Width = 121
+ Height = 34
Caption = 'Table Filter'
TabOrder = 19
OnClick = btnTableFilterClick
end
object btnPartitioning: TButton
- Left = 360
- Top = 908
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 363
+ Width = 121
+ Height = 33
Caption = 'Table Partitioning'
TabOrder = 20
OnClick = btnPartitioningClick
end
object btnCRUDWithGUID: TButton
- Left = 20
- Top = 118
- Width = 303
- Height = 82
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 47
+ Width = 121
+ Height = 33
Caption = 'CRUD (with GUID PK)'
TabOrder = 21
OnClick = btnCRUDWithGUIDClick
end
object btnOOP: TButton
- Left = 360
- Top = 1005
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 402
+ Width = 121
+ Height = 34
Caption = 'OOP with Partitioning and Filtering'
TabOrder = 22
WordWrap = True
OnClick = btnOOPClick
end
object btnReadOnly: TButton
- Left = 20
- Top = 1105
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 442
+ Width = 121
+ Height = 34
Caption = 'Read/Only Entities'
TabOrder = 23
OnClick = btnReadOnlyClick
end
object btnSpeed: TButton
- Left = 20
- Top = 1205
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 8
+ Top = 482
+ Width = 121
+ Height = 34
Caption = 'Metadata Speed Test'
TabOrder = 24
OnClick = btnSpeedClick
end
object btnRefresh: TButton
- Left = 360
- Top = 1105
- Width = 303
- Height = 85
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 8
+ Left = 144
+ Top = 442
+ Width = 121
+ Height = 34
Caption = 'Manual Refresh'
TabOrder = 25
OnClick = btnRefreshClick
end
+ object btnNamedQuery: TButton
+ Left = 144
+ Top = 482
+ Width = 121
+ Height = 34
+ Caption = 'Named Query'
+ TabOrder = 26
+ OnClick = btnNamedQueryClick
+ end
+ object btnVirtualEntities: TButton
+ Left = 144
+ Top = 522
+ Width = 121
+ Height = 34
+ Caption = 'Virtual Entities'
+ TabOrder = 27
+ OnClick = btnVirtualEntitiesClick
+ end
object FDConnection1: TFDConnection
Left = 312
Top = 40
diff --git a/samples/activerecord_showcase/MainFormU.pas b/samples/activerecord_showcase/MainFormU.pas
index 2dd5fdf2..1bff37e1 100644
--- a/samples/activerecord_showcase/MainFormU.pas
+++ b/samples/activerecord_showcase/MainFormU.pas
@@ -58,6 +58,8 @@ type
btnReadOnly: TButton;
btnSpeed: TButton;
btnRefresh: TButton;
+ btnNamedQuery: TButton;
+ btnVirtualEntities: TButton;
procedure btnCRUDClick(Sender: TObject);
procedure btnInheritanceClick(Sender: TObject);
procedure btnMultiThreadingClick(Sender: TObject);
@@ -86,6 +88,8 @@ type
procedure btnReadOnlyClick(Sender: TObject);
procedure btnSpeedClick(Sender: TObject);
procedure btnRefreshClick(Sender: TObject);
+ procedure btnNamedQueryClick(Sender: TObject);
+ procedure btnVirtualEntitiesClick(Sender: TObject);
private
procedure Log(const Value: string);
procedure LoadCustomers;
@@ -649,6 +653,61 @@ begin
'in(City,["Rome","New York","London","Melbourne","Berlin"])').ToString + ' records');
end;
+procedure TMainForm.btnNamedQueryClick(Sender: TObject);
+begin
+ Log('** Named SQL Query');
+ Log('QuerySQL: RatingLessThanPar');
+ var lCustomers := TMVCActiveRecord.SelectByNamedQuery('RatingLessThanPar', [4], [ftInteger]);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ Log('QuerySQL: RatingEqualsToPar');
+ lCustomers := TMVCActiveRecord.SelectByNamedQuery('RatingEqualsToPar', [3], [ftInteger]);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ Log('** Named RQL Query');
+ Log('QueryRQL: RatingLessThanPar');
+ lCustomers := TMVCActiveRecord.SelectRQLByNamedQuery('RatingLessThanPar', [4], 1000);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+ Log('QueryRQL: RatingEqualsToPar');
+ lCustomers := TMVCActiveRecord.SelectRQLByNamedQuery('RatingEqualsToPar', [3], 1000);
+ try
+ for var lCustomer in lCustomers do
+ begin
+ Log(Format('%4d - %8.5s - %s', [lCustomer.ID.ValueOrDefault, lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault]));
+ end;
+ finally
+ lCustomers.Free;
+ end;
+
+
+end;
+
procedure TMainForm.btnNullablesClick(Sender: TObject);
var
lCustomer: TCustomer;
@@ -1040,6 +1099,7 @@ var
lItem: TMVCActiveRecord;
lCustomer: TCustomer;
lCustList: TObjectList;
+ lRecCount: Integer;
const
cRQL1 = 'in(City,["Rome","London"]);sort(+code);limit(0,50)';
cRQL2 = 'and(eq(City,"Rome"),or(contains(CompanyName,"GAS"),contains(CompanyName,"Motors")))';
@@ -1133,6 +1193,114 @@ begin
lList.Free;
end;
+
+ //******************************************************
+ // Using "Load" methods ********************************
+ //******************************************************
+ Log('*************************************************');
+ Log('** RQL Queries Test (using "Load" style methods)');
+ Log('*************************************************');
+ Log('>> RQL Query (1) - ' + cRQL1);
+ lList := TMVCActiveRecordList.Create;
+ try
+ TMVCActiveRecord.SelectRQL(TCustomer, cRQL1, 20, lList);
+ Log(lList.Count.ToString + ' record/s found');
+ for lItem in lList do
+ begin
+ lCustomer := TCustomer(lItem);
+ Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
+ end;
+ finally
+ lList.Free;
+ end;
+
+ Log('>> RQL Query (2) - ' + cRQL2);
+ lCustList := TObjectList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(cRQL2, 20, lCustList);
+ 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;
+
+ Log('**RQL Query (3) - ' + cRQL2);
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, cRQL2, 20, lList);
+ Log(lRecCount.ToString + ' record/s found');
+ for lItem in lList do
+ begin
+ lCustomer := TCustomer(lItem);
+ Log(Format('%5s - %s (%s)', [lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault, lCustomer.City]));
+ end;
+ finally
+ lList.Free;
+ end;
+
+ Log('**RQL Query (4) - with limit 20');
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, '', 20, lList);
+ Log(lRecCount.ToString + ' record/s found');
+ Assert(lRecCount = 20);
+ Assert(lList.Count = lRecCount);
+ finally
+ lList.Free;
+ end;
+
+ Log('**RQL Query (5) - sort by code with limit 20');
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, 'sort(+code)', 20, lList);
+ Log(lRecCount.ToString + ' record/s found');
+ Assert(lRecCount = lList.Count);
+ Assert(lList.Count = 20);
+ finally
+ lList.Free;
+ end;
+
+ Log('**RQL Query (6) - with limit 10');
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, '', 10, lList);
+ Log(lList.Count.ToString + ' record/s found');
+ Assert(lRecCount = lList.Count);
+ Assert(lList.Count = 10);
+ finally
+ lList.Free;
+ end;
+
+ Log('**RQL Query (7) - with limit 1');
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, '', 1, lList);
+ Log(lList.Count.ToString + ' record/s found');
+ Assert(lList.Count = 1);
+ Assert(lRecCount = lList.Count);
+ finally
+ lList.Free;
+ end;
+
+ Log('**RQL Query (8) - with limit 0');
+ lList := TMVCActiveRecordList.Create;
+ try
+ lRecCount := TMVCActiveRecord.SelectRQL(TCustomer, '', 0, lList);
+ Log(lList.Count.ToString + ' record/s found');
+ Assert(lList.Count = 0);
+ Assert(lRecCount = lList.Count);
+ finally
+ lList.Free;
+ end;
+
+
+
end;
procedure TMainForm.btnSelectClick(Sender: TObject);
@@ -1541,6 +1709,24 @@ begin
end;
end;
+procedure TMainForm.btnVirtualEntitiesClick(Sender: TObject);
+begin
+ var lCustStats := TMVCActiveRecord.SelectByNamedQuery('CustomersInTheSameCity', [], []);
+ try
+ for var lCustomer in lCustStats do
+ begin
+ Log(Format('%4d - %8.5s - %s - (%d other customers in the same city)', [
+ lCustomer.ID.ValueOrDefault,
+ lCustomer.Code.ValueOrDefault,
+ lCustomer.CompanyName.ValueOrDefault,
+ lCustomer.CustomersInTheSameCity
+ ]));
+ end;
+ finally
+ lCustStats.Free;
+ end;
+end;
+
procedure TMainForm.btnWithSpacesClick(Sender: TObject);
var
lCustomer: TCustomerWithSpaces;
diff --git a/samples/commons/BusinessObjectsU.pas b/samples/commons/BusinessObjectsU.pas
index 4d06c451..61a8505d 100644
--- a/samples/commons/BusinessObjectsU.pas
+++ b/samples/commons/BusinessObjectsU.pas
@@ -203,7 +203,7 @@ type
TInterfacedPerson = class(TInterfacedObject, IPerson)
private
fName: string;
- FDOB: TDate;
+ fDOB: TDate;
fAge: Integer;
protected
function GetName: string;
@@ -213,9 +213,10 @@ type
function GetDOB: TDate;
procedure SetDOB(const Value: TDate);
public
- property name: string read GetName write SetName;
+ property Name: string read GetName write SetName;
property Age: Integer read GetAge write SetAge;
property DOB: TDate read GetDOB write SetDOB;
+ constructor Create(Name: String; Age: Integer; DOB: TDate); virtual;
end;
//TPeople = class(TObjectList);
@@ -651,6 +652,14 @@ end;
{ TInterfacedPerson }
+constructor TInterfacedPerson.Create(Name: String; Age: Integer; DOB: TDate);
+begin
+ inherited Create;
+ fName := Name;
+ fAge := Age;
+ fDOB := DOB;
+end;
+
function TInterfacedPerson.GetAge: Integer;
begin
Result := fAge;
diff --git a/samples/data/activerecorddb_firebird_script.sql b/samples/data/activerecorddb_firebird_script.sql
index c9daae32..1640d1b2 100644
--- a/samples/data/activerecorddb_firebird_script.sql
+++ b/samples/data/activerecorddb_firebird_script.sql
@@ -7,7 +7,7 @@ CREATE TABLE articles (
CREATE TABLE customers (
id integer GENERATED BY DEFAULT AS IDENTITY,
- code varchar(20) NOT NULL,
+ code varchar(20),
description varchar(200),
city varchar(200),
rating INTEGER,
diff --git a/samples/data/people_dataset.json b/samples/data/people_dataset.json
new file mode 100644
index 00000000..5b7bd3ea
--- /dev/null
+++ b/samples/data/people_dataset.json
@@ -0,0 +1 @@
+{"FDBS":{"Version":16,"Manager":{"UpdatesRegistry":true,"TableList":[{"class":"Table","Name":"FDMemTable1","SourceName":"FDMemTable1","TabID":0,"EnforceConstraints":false,"MinimumCapacity":50,"CheckNotNull":false,"ColumnList":[{"class":"Column","Name":"id","SourceName":"id","SourceID":1,"DataType":"Int64","Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OInKey":true,"OriginColName":"id"},{"class":"Column","Name":"last_name","SourceName":"last_name","SourceID":2,"DataType":"WideString","Size":100,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"last_name","SourceSize":100},{"class":"Column","Name":"first_name","SourceName":"first_name","SourceID":3,"DataType":"WideString","Size":100,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"first_name","SourceSize":100},{"class":"Column","Name":"dob","SourceName":"dob","SourceID":4,"DataType":"Date","Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"dob"},{"class":"Column","Name":"full_name","SourceName":"full_name","SourceID":5,"DataType":"WideString","Size":80,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"full_name","SourceSize":80},{"class":"Column","Name":"is_male","SourceName":"is_male","SourceID":6,"DataType":"Boolean","Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"is_male"},{"class":"Column","Name":"note","SourceName":"note","SourceID":7,"DataType":"WideMemo","Searchable":true,"AllowNull":true,"BlobData":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"note"},{"class":"Column","Name":"photo","SourceName":"photo","SourceID":8,"DataType":"Blob","Searchable":true,"AllowNull":true,"BlobData":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"photo"},{"class":"Column","Name":"person_type","SourceName":"person_type","SourceID":9,"DataType":"WideString","Size":8190,"Searchable":true,"AllowNull":true,"BlobData":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"person_type","SourceSize":8190},{"class":"Column","Name":"salary","SourceName":"salary","SourceID":10,"DataType":"Currency","Precision":19,"Scale":4,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"salary","SourcePrecision":19,"SourceScale":4},{"class":"Column","Name":"annual_bonus","SourceName":"annual_bonus","SourceID":11,"DataType":"Currency","Precision":19,"Scale":4,"Searchable":true,"AllowNull":true,"Base":true,"OAllowNull":true,"OInUpdate":true,"OInWhere":true,"OriginColName":"annual_bonus","SourcePrecision":19,"SourceScale":4}],"ConstraintList":[],"ViewList":[],"RowList":[{"RowID":0,"Original":{"id":235,"last_name":"Richards","first_name":"Reed","dob":"19851104","full_name":"Reed Richards","is_male":true,"person_type":"person","photo":""}},{"RowID":1,"Original":{"id":236,"last_name":"Parker","first_name":"Peter","dob":"19851104","full_name":"Peter Parker","is_male":true,"person_type":"employee","salary":2100,"photo":""}},{"RowID":2,"Original":{"id":237,"last_name":"Storm","first_name":"Sue","dob":"19751014","full_name":"Sue Storm","is_male":false,"person_type":"employee","salary":2200,"photo":""}},{"RowID":3,"Original":{"id":238,"last_name":"Banner","first_name":"Bruce","dob":"19751104","full_name":"Bruce Banner","is_male":true,"person_type":"manager","salary":2800,"annual_bonus":5000,"photo":""}}]}],"RelationList":[],"UpdatesJournal":{"SavePoint":4,"Changes":[]}}}}
\ No newline at end of file
diff --git a/samples/funcion_actions_showcase/ControllerU.pas b/samples/funcion_actions_showcase/ControllerU.pas
new file mode 100644
index 00000000..8fb632d3
--- /dev/null
+++ b/samples/funcion_actions_showcase/ControllerU.pas
@@ -0,0 +1,246 @@
+unit ControllerU;
+
+interface
+
+uses
+ MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons,
+ System.Generics.Collections, Data.DB;
+
+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;
+ constructor Create(FirstName, LastName: String; Age: Integer);
+ 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;
+
+ { actions returning objects }
+ [MVCPath('/objects/single')]
+ function GetSingleObject: TPerson;
+ [MVCPath('/objects/multiple')]
+ function GetMultipleObjects: TObjectList;
+
+ { actions returning datasets }
+ [MVCPath('/datasets/single')]
+ function GetSingleDataSet: TDataSet;
+ [MVCPath('/datasets/multiple')]
+ function GetMultipleDataSet: TEnumerable;
+ [MVCPath('/datasets/multiple2')]
+ function GetMultipleDataSet2: IMVCObjectDictionary;
+
+ { customize response headers }
+ [MVCPath('/headers')]
+ function GetWithCustomHeaders: TObjectList;
+
+ { using IMVCResponse }
+ [MVCPath('/mvcresponse/message')]
+ function GetMVCResponseSimple: IMVCResponse;
+ [MVCPath('/mvcresponse/data')]
+ function GetMVCResponseWithData: IMVCResponse;
+ [MVCPath('/mvcresponse/list')]
+ function GetMVCResponseWithObjectList: IMVCResponse;
+ [MVCPath('/mvcresponse/dictionary')]
+ function GetMVCResponseWithObjectDictionary: IMVCResponse;
+ [MVCPath('/mvcresponse/error')]
+ function GetMVCErrorResponse: IMVCResponse;
+ end;
+
+implementation
+
+uses
+ System.SysUtils, MVCFramework.Logger, System.StrUtils, System.DateUtils,
+ MainDMU, FireDAC.Comp.Client, MVCFramework.FireDAC.Utils;
+
+{ TMyController }
+
+function TMyController.GetMultipleDataSet: TEnumerable;
+begin
+ var lDM := TdmMain.Create(nil);
+ try
+ lDM.dsPeople.Open;
+ var lList := TObjectList.Create;
+ lList.Add(TFDMemTable.CloneFrom(lDM.dsPeople));
+ lList.Add(TFDMemTable.CloneFrom(lDM.dsPeople));
+ Result := lList;
+ finally
+ lDM.Free;
+ end;
+end;
+
+function TMyController.GetMultipleDataSet2: IMVCObjectDictionary;
+begin
+ var lDM := TdmMain.Create(nil);
+ try
+ lDM.dsPeople.Open;
+ Result := ObjectDict()
+ .Add('people1', TFDMemTable.CloneFrom(lDM.dsPeople))
+ .Add('people2', TFDMemTable.CloneFrom(lDM.dsPeople));
+ finally
+ lDM.Free;
+ end;
+end;
+
+function TMyController.GetMultipleObjects: TObjectList;
+begin
+ Result := TObjectList.Create;
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', YearsBetween(Date, EncodeDateDay(1979, 1))));
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', Result[0].Age + 10));
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', Result[0].Age + 20));
+end;
+
+function TMyController.GetMultipleRecords: TArray;
+begin
+ SetLength(Result, 3);
+ Result[0] := TPersonRec.Create;
+ Result[1] := TPersonRec.Create;
+ Result[2] := TPersonRec.Create;
+
+ Inc(Result[1].Age, 10);
+
+ Inc(Result[2].Age, 20);
+end;
+
+function TMyController.GetMVCErrorResponse: IMVCResponse;
+begin
+ Result := TMVCErrorResponse.Create(500, 'boom');
+end;
+
+function TMyController.GetMVCResponseSimple: IMVCResponse;
+begin
+ Result := MVCResponse(HTTP_STATUS.OK, 'My Message', 'My Reason String');
+end;
+
+function TMyController.GetMVCResponseWithData: IMVCResponse;
+begin
+ Result := MVCResponse(HTTP_STATUS.OK, TPerson.Create('Daniele','Teti', 99));
+end;
+
+function TMyController.GetMVCResponseWithObjectDictionary: IMVCResponse;
+begin
+ Result := MVCResponse(
+ HTTP_STATUS.OK,
+ ObjectDict()
+ .Add('people1', TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ )
+ .Add('people2', TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ )
+ );
+end;
+
+function TMyController.GetMVCResponseWithObjectList: IMVCResponse;
+begin
+ Result := MVCResponse(
+ HTTP_STATUS.OK,
+ TObjectList.Create([
+ TPerson.Create('Daniele','Teti', 99),
+ TPerson.Create('Peter','Parker', 25),
+ TPerson.Create('Bruce','Banner', 45)
+ ])
+ );
+end;
+
+function TMyController.GetSingleDataSet: TDataSet;
+begin
+ var lDM := TdmMain.Create(nil);
+ try
+ lDM.dsPeople.Open;
+ Result := TFDMemTable.CloneFrom(lDM.dsPeople);
+ finally
+ lDM.Free;
+ end;
+end;
+
+function TMyController.GetSingleObject: TPerson;
+begin
+ Result := TPerson.Create('Daniele', 'Teti', YearsBetween(Date, EncodeDateDay(1979, 1)));
+end;
+
+function TMyController.GetSingleRecord: TPersonRec;
+begin
+ Result := TPersonRec.Create;
+end;
+
+function TMyController.GetSum(const A, B: Integer): Integer;
+begin
+ Result := A + B;
+end;
+
+function TMyController.GetSumAsFloat(const A, B: Extended): Extended;
+begin
+ Result := A + B;
+end;
+
+function TMyController.GetWithCustomHeaders: TObjectList;
+begin
+ Result := TObjectList.Create;
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', YearsBetween(Date, EncodeDateDay(1979, 1))));
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', Result[0].Age + 10));
+
+ Result.Add(TPerson.Create('Daniele', 'Teti', Result[0].Age + 20));
+
+ { customize headers }
+ Context.Response.StatusCode := HTTP_STATUS.PartialContent;
+ Context.Response.ContentType := TMVCMediaType.APPLICATION_JSON;
+ Context.Response.SetCustomHeader('X-MYHEADER', 'HELLO WORLD');
+end;
+
+{ TPersonRec }
+
+class function TPersonRec.Create: TPersonRec;
+begin
+ Result.FirstName := 'Daniele';
+ Result.LastName := 'Teti';
+ Result.Age := YearsBetween(Date, EncodeDateDay(1979, 1));
+end;
+
+{ TPerson }
+
+constructor TPerson.Create(FirstName, LastName: String; Age: Integer);
+begin
+ inherited Create;
+ fFirstName := FirstName;
+ fLastName := LastName;
+ fAge := Age;
+end;
+
+end.
diff --git a/samples/funcion_actions_showcase/MainDMU.dfm b/samples/funcion_actions_showcase/MainDMU.dfm
new file mode 100644
index 00000000..6a3e36e8
--- /dev/null
+++ b/samples/funcion_actions_showcase/MainDMU.dfm
@@ -0,0 +1,101 @@
+object dmMain: TdmMain
+ Height = 162
+ Width = 312
+ object dsPeople: TFDMemTable
+ Active = True
+ FetchOptions.AssignedValues = [evMode]
+ FetchOptions.Mode = fmAll
+ ResourceOptions.AssignedValues = [rvPersistent, rvSilentMode]
+ ResourceOptions.Persistent = True
+ ResourceOptions.SilentMode = True
+ UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates]
+ UpdateOptions.CheckRequired = False
+ UpdateOptions.AutoCommitUpdates = True
+ Left = 176
+ Top = 88
+ Content = {
+ 4144425310000000CA060000FF00010001FF02FF03040016000000460044004D
+ 0065006D005400610062006C0065003100050016000000460044004D0065006D
+ 005400610062006C0065003100060000000000070000080032000000090000FF
+ 0AFF0B04000400000069006400050004000000690064000C00010000000E000D
+ 000F000110000111000112000113000114000115000116000400000069006400
+ FEFF0B0400120000006C006100730074005F006E0061006D0065000500120000
+ 006C006100730074005F006E0061006D0065000C00020000000E001700180064
+ 0000000F00011000011100011200011300011400011600120000006C00610073
+ 0074005F006E0061006D006500190064000000FEFF0B04001400000066006900
+ 7200730074005F006E0061006D00650005001400000066006900720073007400
+ 5F006E0061006D0065000C00030000000E0017001800640000000F0001100001
+ 110001120001130001140001160014000000660069007200730074005F006E00
+ 61006D006500190064000000FEFF0B04000600000064006F0062000500060000
+ 0064006F0062000C00040000000E001A000F0001100001110001120001130001
+ 14000116000600000064006F006200FEFF0B040012000000660075006C006C00
+ 5F006E0061006D006500050012000000660075006C006C005F006E0061006D00
+ 65000C00050000000E0017001800500000000F00011000011100011200011300
+ 01140001160012000000660075006C006C005F006E0061006D00650019005000
+ 0000FEFF0B04000E000000690073005F006D0061006C00650005000E00000069
+ 0073005F006D0061006C0065000C00060000000E001B000F0001100001110001
+ 12000113000114000116000E000000690073005F006D0061006C006500FEFF0B
+ 0400080000006E006F00740065000500080000006E006F00740065000C000700
+ 00000E001C000F00011000011D00011100011200011300011400011600080000
+ 006E006F0074006500FEFF0B04000A000000700068006F0074006F0005000A00
+ 0000700068006F0074006F000C00080000000E001E000F00011000011D000111
+ 000112000113000114000116000A000000700068006F0074006F00FEFF0B0400
+ 1600000070006500720073006F006E005F007400790070006500050016000000
+ 70006500720073006F006E005F0074007900700065000C00090000000E001700
+ 1800FE1F00000F00011000011D00011100011200011300011400011600160000
+ 0070006500720073006F006E005F0074007900700065001900FE1F0000FEFF0B
+ 04000C000000730061006C0061007200790005000C000000730061006C006100
+ 720079000C000A0000000E001F002000130000002100040000000F0001100001
+ 11000112000113000114000116000C000000730061006C006100720079002200
+ 13000000230004000000FEFF0B04001800000061006E006E00750061006C005F
+ 0062006F006E007500730005001800000061006E006E00750061006C005F0062
+ 006F006E00750073000C000B0000000E001F002000130000002100040000000F
+ 000110000111000112000113000114000116001800000061006E006E00750061
+ 006C005F0062006F006E0075007300220013000000230004000000FEFEFF24FE
+ FF25FEFF26FF27280000000000FF290000EB0000000000000001001000000052
+ 00690063006800610072006400730002000800000052006500650064000300D5
+ 0F0B0004001A0000005200650065006400200052006900630068006100720064
+ 0073000500FFFF08000C00000070006500720073006F006E00FEFEFF27280001
+ 000000FF290000EC0000000000000001000C0000005000610072006B00650072
+ 0002000A000000500065007400650072000300D50F0B00040018000000500065
+ 0074006500720020005000610072006B00650072000500FFFF08001000000065
+ 006D0070006C006F007900650065000900406F400100000000FEFEFF27280002
+ 000000FF290000ED0000000000000001000A000000530074006F0072006D0002
+ 000600000053007500650003007B010B00040012000000530075006500200053
+ 0074006F0072006D000500000008001000000065006D0070006C006F00790065
+ 006500090080B14F0100000000FEFEFF27280003000000FF290000EE00000000
+ 00000001000C000000420061006E006E006500720002000A0000004200720075
+ 0063006500030090010B00040018000000420072007500630065002000420061
+ 006E006E00650072000500FFFF08000E0000006D0061006E0061006700650072
+ 000900003FAB01000000000A0080F0FA0200000000FEFEFEFEFEFF2AFEFF2B2C
+ 0004000000FF2DFEFEFE0E004D0061006E0061006700650072001E0055007000
+ 6400610074006500730052006500670069007300740072007900120054006100
+ 62006C0065004C006900730074000A005400610062006C00650008004E006100
+ 6D006500140053006F0075007200630065004E0061006D0065000A0054006100
+ 620049004400240045006E0066006F0072006300650043006F006E0073007400
+ 7200610069006E00740073001E004D0069006E0069006D0075006D0043006100
+ 700061006300690074007900180043006800650063006B004E006F0074004E00
+ 75006C006C00140043006F006C0075006D006E004C006900730074000C004300
+ 6F006C0075006D006E00100053006F007500720063006500490044000E006400
+ 740049006E007400360034001000440061007400610054007900700065001400
+ 530065006100720063006800610062006C006500120041006C006C006F007700
+ 4E0075006C006C000800420061007300650014004F0041006C006C006F007700
+ 4E0075006C006C0012004F0049006E0055007000640061007400650010004F00
+ 49006E00570068006500720065000C004F0049006E004B00650079001A004F00
+ 72006900670069006E0043006F006C004E0061006D0065001800640074005700
+ 69006400650053007400720069006E0067000800530069007A00650014005300
+ 6F007500720063006500530069007A0065000C00640074004400610074006500
+ 12006400740042006F006F006C00650061006E00140064007400570069006400
+ 65004D0065006D006F00100042006C006F00620044006100740061000C006400
+ 740042006C006F006200140064007400430075007200720065006E0063007900
+ 120050007200650063006900730069006F006E000A005300630061006C006500
+ 1E0053006F00750072006300650050007200650063006900730069006F006E00
+ 160053006F0075007200630065005300630061006C0065001C0043006F006E00
+ 730074007200610069006E0074004C0069007300740010005600690065007700
+ 4C006900730074000E0052006F0077004C00690073007400060052006F007700
+ 0A0052006F0077004900440010004F0072006900670069006E0061006C001800
+ 520065006C006100740069006F006E004C006900730074001C00550070006400
+ 61007400650073004A006F00750072006E0061006C0012005300610076006500
+ 50006F0069006E0074000E004300680061006E00670065007300}
+ end
+end
diff --git a/samples/funcion_actions_showcase/MainDMU.pas b/samples/funcion_actions_showcase/MainDMU.pas
new file mode 100644
index 00000000..cb1384b1
--- /dev/null
+++ b/samples/funcion_actions_showcase/MainDMU.pas
@@ -0,0 +1,26 @@
+unit MainDMU;
+
+interface
+
+uses
+ System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
+ FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
+ FireDAC.DApt.Intf, FireDAC.Stan.StorageBin, Data.DB, FireDAC.Comp.DataSet,
+ FireDAC.Comp.Client;
+
+type
+ TdmMain = class(TDataModule)
+ dsPeople: TFDMemTable;
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+implementation
+
+{%CLASSGROUP 'System.Classes.TPersistent'}
+
+{$R *.dfm}
+
+end.
diff --git a/samples/funcion_actions_showcase/WebModuleU.dfm b/samples/funcion_actions_showcase/WebModuleU.dfm
new file mode 100644
index 00000000..02d66b97
--- /dev/null
+++ b/samples/funcion_actions_showcase/WebModuleU.dfm
@@ -0,0 +1,7 @@
+object MyWebModule: TMyWebModule
+ OnCreate = WebModuleCreate
+ OnDestroy = WebModuleDestroy
+ Actions = <>
+ Height = 230
+ Width = 415
+end
diff --git a/samples/funcion_actions_showcase/WebModuleU.pas b/samples/funcion_actions_showcase/WebModuleU.pas
new file mode 100644
index 00000000..1bd9f21e
--- /dev/null
+++ b/samples/funcion_actions_showcase/WebModuleU.pas
@@ -0,0 +1,71 @@
+unit WebModuleU;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ Web.HTTPApp,
+ MVCFramework;
+
+type
+ TMyWebModule = class(TWebModule)
+ procedure WebModuleCreate(Sender: TObject);
+ procedure WebModuleDestroy(Sender: TObject);
+ private
+ FMVC: TMVCEngine;
+ public
+ { Public declarations }
+ end;
+
+var
+ WebModuleClass: TComponentClass = TMyWebModule;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ System.IOUtils,
+ MVCFramework.Commons,
+ ControllerU;
+
+procedure TMyWebModule.WebModuleCreate(Sender: TObject);
+begin
+ FMVC := TMVCEngine.Create(Self,
+ procedure(Config: TMVCConfig)
+ begin
+ Config.dotEnv := dotEnv;
+ // session timeout (0 means session cookie)
+ Config[TMVCConfigKey.SessionTimeout] := dotEnv.Env('dmvc.session_timeout', '0');
+ //default content-type
+ Config[TMVCConfigKey.DefaultContentType] := dotEnv.Env('dmvc.default.content_type', TMVCConstants.DEFAULT_CONTENT_TYPE);
+ //default content charset
+ Config[TMVCConfigKey.DefaultContentCharset] := dotEnv.Env('dmvc.default.content_charset', TMVCConstants.DEFAULT_CONTENT_CHARSET);
+ //unhandled actions are permitted?
+ Config[TMVCConfigKey.AllowUnhandledAction] := dotEnv.Env('dmvc.allow_unhandled_actions', 'false');
+ //enables or not system controllers loading (available only from localhost requests)
+ Config[TMVCConfigKey.LoadSystemControllers] := dotEnv.Env('dmvc.load_system_controllers', 'true');
+ //default view file extension
+ Config[TMVCConfigKey.DefaultViewFileExtension] := dotEnv.Env('dmvc.default.view_file_extension', 'html');
+ //view path
+ Config[TMVCConfigKey.ViewPath] := dotEnv.Env('dmvc.view_path', 'templates');
+ //Max Record Count for automatic Entities CRUD
+ Config[TMVCConfigKey.MaxEntitiesRecordCount] := dotEnv.Env('dmvc.max_entities_record_count', IntToStr(TMVCConstants.MAX_RECORD_COUNT));
+ //Enable Server Signature in response
+ Config[TMVCConfigKey.ExposeServerSignature] := dotEnv.Env('dmvc.expose_server_signature', 'false');
+ //Enable X-Powered-By Header in response
+ Config[TMVCConfigKey.ExposeXPoweredBy] := dotEnv.Env('dmvc.expose_x_powered_by', 'true');
+ // Max request size in bytes
+ Config[TMVCConfigKey.MaxRequestSize] := dotEnv.Env('dmvc.max_request_size', IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE));
+ end);
+ FMVC.AddController(TMyController);
+
+end;
+
+procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
+begin
+ FMVC.Free;
+end;
+
+end.
diff --git a/samples/funcion_actions_showcase/function_actions_showcase.dpr b/samples/funcion_actions_showcase/function_actions_showcase.dpr
new file mode 100644
index 00000000..5d304a46
--- /dev/null
+++ b/samples/funcion_actions_showcase/function_actions_showcase.dpr
@@ -0,0 +1,83 @@
+program function_actions_showcase;
+
+{$APPTYPE CONSOLE}
+
+uses
+ System.SysUtils,
+ MVCFramework,
+ MVCFramework.Logger,
+ MVCFramework.DotEnv,
+ MVCFramework.Commons,
+ MVCFramework.Signal,
+ Web.ReqMulti,
+ Web.WebReq,
+ Web.WebBroker,
+ IdContext,
+ IdHTTPWebBrokerBridge,
+ ControllerU in 'ControllerU.pas',
+ WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule},
+ MainDMU in 'MainDMU.pas' {dmMain: TDataModule};
+
+{$R *.res}
+
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
+ LServer.DefaultPort := APort;
+ LServer.KeepAlive := True;
+ LServer.MaxConnections := dotEnv.Env('dmvc.webbroker.max_connections', 0);
+ LServer.ListenQueue := dotEnv.Env('dmvc.indy.listen_queue', 500);
+
+ LServer.Active := True;
+ WriteLn('Listening on port ', APort);
+ Write('CTRL+C to shutdown the server');
+ WaitForTerminationSignal;
+ EnterInShutdownState;
+ LServer.Active := False;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ { Enable ReportMemoryLeaksOnShutdown during debug }
+ // ReportMemoryLeaksOnShutdown := True;
+ IsMultiThread := True;
+
+ // DMVCFramework Specific Configuration
+ // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.
+ // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.
+ MVCSerializeNulls := True;
+
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+
+ dotEnvConfigure(
+ function: IMVCDotEnv
+ begin
+ Result := NewDotEnv
+ .WithStrategy(TMVCDotEnvPriority.FileThenEnv)
+ //if available, by default, loads default environment (.env)
+ .UseProfile('test') //if available loads the test environment (.env.test)
+ .UseProfile('prod') //if available loads the prod environment (.env.prod)
+ .UseLogger(procedure(LogItem: String)
+ begin
+ LogW('dotEnv: ' + LogItem);
+ end)
+ .Build(); //uses the executable folder to look for .env* files
+ end);
+
+ WebRequestHandlerProc.MaxConnections := dotEnv.Env('dmvc.handler.max_connections', 1024);
+ RunServer(dotEnv.Env('dmvc.server.port', 8080));
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end;
+end.
diff --git a/packages/d111/dmvcframeworkRT.dproj b/samples/funcion_actions_showcase/function_actions_showcase.dproj
similarity index 75%
rename from packages/d111/dmvcframeworkRT.dproj
rename to samples/funcion_actions_showcase/function_actions_showcase.dproj
index 78f3dec3..98497095 100644
--- a/packages/d111/dmvcframeworkRT.dproj
+++ b/samples/funcion_actions_showcase/function_actions_showcase.dproj
@@ -1,14 +1,14 @@
- {96D17257-AF74-48CB-9893-7BCCB56A069D}
- dmvcframeworkRT.dpk
+ {84012097-1BD4-41B3-A479-B831D1147725}
19.5
None
True
Debug
Win32
1
- Package
+ Console
+ function_actions_showcase.dpr
true
@@ -23,6 +23,11 @@
Base
true
+
+ true
+ Base
+ true
+
true
Base
@@ -57,37 +62,34 @@
false
false
false
- true
- true
System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- All
- dmvcframeworkRT
- true
- 1040
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- DMVCFramework - CopyRight (2010-2020) Daniele Teti and the DMVCFramework Team
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ $(DMVC);$(DCC_UnitSearchPath)
+ VCL;$(DCC_Framework)
+ function_actions_showcase
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;fmxase;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+
+
+ DataSnapServer;fmx;emshosting;DbxCommonDriver;bindengine;FireDACCommonODBC;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;dbxcds;emsedge;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;dbexpress;FireDACInfxDriver;Python;inet;DataSnapCommon;dbrtl;FireDACOracleDriver;Skia.Package.FMX;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;dsnapxml;DataSnapClient;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;xmlrtl;dsnap;CloudService;FireDACDb2Driver;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ RaizeComponentsVcl;JvNet;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;frxe28;frxTee28;bindcompvclwinx;Prometheus.Client.Core;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;JvBands;inetdb;JvAppFrm;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;JclVcl;SVGIconImageListFMX;vclactnband;TeeUI;fmxFireDAC;dbexpress;Jcl;JvManagedThreads;FireDACInfxDriver;Python;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;JvPascalInterpreter;PythonVcl;vcltouch;fmxase;frx28;JvPluginSystem;DBXOdbcDriver;DzHTMLText_FMX;dbrtl;JvDB;FireDACDBXDriver;FireDACOracleDriver;ComPortDrv;fmxdae;TeeDB;Skia.Package.FMX;JvTimeFramework;FireDACMSAccDriver;JvCustom;CustomIPTransport;FireDACMSSQLDriver;JvSystem;SVGIconPackage;DataSnapIndy10ServerTransport;JclDeveloperTools;JvControls;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;JvCrypt;FireDACMongoDBDriver;JvJans;JvMM;IndySystem;JvWizards;frxDB28;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;JvGlobus;vcldb;ibxbindings;IconFontsImageList;JclContainers;SynEditDR;JvPageComps;vclFireDAC;JvCore;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;dmvcframeworkDT;bindcompdbx;DzHTMLText_VCL;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;JvDotNetCtrls;JvHMI;DBXSybaseASEDriver;JvRuntimeDesign;DBXDb2Driver;JvXPCtrls;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;JvStdCtrls;ibxpress;JvDlgs;JvDocking;bindcompvcl;dsnap;JvPrintPreview;JvCmp;dmvcframeworkRT;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;IconFontsImageListFMX;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;SVGIconImageList;soapserver;FireDACIBDriver;$(DCC_UsePackage)
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
Debug
- true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
1033
- DMVCFramework - CopyRight (2010-2021) Daniele Teti and the DMVCFramework Team
- rtl;dbrtl;IndySystem;IndyProtocols;IndyCore;dmvcframeworkDT;$(DCC_UsePackage)
- 110
- rtl;dbrtl;IndySystem;IndyProtocols;IndyCore;$(DCC_UsePackage)
+ RaizeComponentsVcl;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;SVGIconImageListFMX;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;Python;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;DBXOdbcDriver;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;FireDACOracleDriver;ComPortDrv;fmxdae;TeeDB;Skia.Package.FMX;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;SVGIconPackage;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;SynEditDR;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;DzHTMLText_VCL;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;SVGIconImageList;soapserver;FireDACIBDriver;$(DCC_UsePackage)
DEBUG;$(DCC_Define)
@@ -96,19 +98,11 @@
true
true
true
+ true
+ true
- true
- 1033
- 3
- true
- false
- true
- CompanyName=Daniele Teti and the DMVCFramework Team;FileDescription=DelphiMVCFramework 3.2.2-nitrogen;FileVersion=3.2.2.0;InternalName=DelphiMVCFramework 3.2.2-nitrogen;LegalCopyright=Daniele Teti and the DMVCFramework Team - Apache License 2;LegalTrademarks=DelphiMVCFramework;OriginalFilename=$(MSBuildProjectName);ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=DelphiMVCFramework;ProductVersion=3.2.2;Comments=
- 3
- 2
- 2
- 111
+ false
false
@@ -120,80 +114,17 @@
MainSource
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ dfm
+ TWebModule
+
+
+
+ dfm
+ TDataModule
+
Base
@@ -208,16 +139,12 @@
Delphi.Personality.12
- Package
+ Console
- dmvcframeworkRT.dpk
+ function_actions_showcase.dpr
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
-
@@ -230,14 +157,17 @@
true
-
true
-
-
+
+
+ function_actions_showcase.exe
+ true
+
+
1
@@ -955,7 +885,6 @@
-
diff --git a/samples/authenticationauthorization/AppControllerU.pas b/samples/middleware_basicauthentication/AppControllerU.pas
similarity index 96%
rename from samples/authenticationauthorization/AppControllerU.pas
rename to samples/middleware_basicauthentication/AppControllerU.pas
index f48a311f..4c9d907d 100644
--- a/samples/authenticationauthorization/AppControllerU.pas
+++ b/samples/middleware_basicauthentication/AppControllerU.pas
@@ -1,87 +1,87 @@
-unit AppControllerU;
-
-interface
-
-uses
- MVCFramework,
- MVCFramework.Commons,
- MVCFramework.Logger,
- Web.HTTPApp;
-
-type
-
- [MVCPath('/')]
- TApp1MainController = class(TMVCController)
- public
- [MVCPath('/public')]
- [MVCHTTPMethod([httpGET])]
- procedure PublicSection;
- [MVCPath('/')]
- [MVCHTTPMethod([httpGET])]
- procedure Index;
- end;
-
- [MVCPath('/admin')]
- TAdminController = class(TMVCController)
- public
- [MVCPath('/role1')]
- [MVCProduces('text/html')]
- [MVCHTTPMethod([httpGET])]
- procedure OnlyRole1;
- [MVCPath('/role1')]
- [MVCProduces('application/json')]
- [MVCHTTPMethod([httpGET])]
- procedure OnlyRole1EmittingJSON;
- [MVCPath('/role2')]
- [MVCProduces('text/html')]
- [MVCHTTPMethod([httpGET])]
- procedure OnlyRole2;
- end;
-
-implementation
-
-uses
- System.SysUtils;
-
-{ TApp1MainController }
-
-procedure TApp1MainController.Index;
-begin
- Redirect('/index.html');
-end;
-
-procedure TApp1MainController.PublicSection;
-begin
- Render('This is a public section');
-end;
-
-{ TAdminController }
-
-procedure TAdminController.OnlyRole1;
-begin
- ContentType := TMVCMediaType.TEXT_PLAIN;
- ResponseStream.AppendLine('Hey! Hello ' + Context.LoggedUser.UserName +
- ', now you are a logged user and this is a protected content!');
- ResponseStream.AppendLine('As logged user you have the following roles: ' +
- sLineBreak + string.Join(sLineBreak, Context.LoggedUser.Roles.ToArray));
- RenderResponseStream;
-end;
-
-procedure TAdminController.OnlyRole1EmittingJSON;
-begin
- ContentType := TMVCMediaType.APPLICATION_JSON;
- Render('This is protected content accessible only by user1: parameter = ' +
- Context.Request.Params['par1']);
-end;
-
-procedure TAdminController.OnlyRole2;
-begin
- ContentType := TMVCMediaType.TEXT_PLAIN;
- ResponseStream.AppendLine('Hey! Hello ' + Context.LoggedUser.UserName +
- ', now you are a logged user and this is a protected content!');
- ResponseStream.AppendLine('As logged user you have the following roles: ' +
- sLineBreak + string.Join(sLineBreak, Context.LoggedUser.Roles.ToArray));
- RenderResponseStream;
-end;
-
-end.
+unit AppControllerU;
+
+interface
+
+uses
+ MVCFramework,
+ MVCFramework.Commons,
+ MVCFramework.Logger,
+ Web.HTTPApp;
+
+type
+
+ [MVCPath('/')]
+ TApp1MainController = class(TMVCController)
+ public
+ [MVCPath('/public')]
+ [MVCHTTPMethod([httpGET])]
+ procedure PublicSection;
+ [MVCPath('/')]
+ [MVCHTTPMethod([httpGET])]
+ procedure Index;
+ end;
+
+ [MVCPath('/admin')]
+ TAdminController = class(TMVCController)
+ public
+ [MVCPath('/role1')]
+ [MVCProduces('text/html')]
+ [MVCHTTPMethod([httpGET])]
+ procedure OnlyRole1;
+ [MVCPath('/role1')]
+ [MVCProduces('application/json')]
+ [MVCHTTPMethod([httpGET])]
+ procedure OnlyRole1EmittingJSON;
+ [MVCPath('/role2')]
+ [MVCProduces('text/html')]
+ [MVCHTTPMethod([httpGET])]
+ procedure OnlyRole2;
+ end;
+
+implementation
+
+uses
+ System.SysUtils;
+
+{ TApp1MainController }
+
+procedure TApp1MainController.Index;
+begin
+ Redirect('/index.html');
+end;
+
+procedure TApp1MainController.PublicSection;
+begin
+ Render('This is a public section');
+end;
+
+{ TAdminController }
+
+procedure TAdminController.OnlyRole1;
+begin
+ ContentType := TMVCMediaType.TEXT_PLAIN;
+ ResponseStream.AppendLine('Hey! Hello ' + Context.LoggedUser.UserName +
+ ', now you are a logged user and this is a protected content!');
+ ResponseStream.AppendLine('As logged user you have the following roles: ' +
+ sLineBreak + string.Join(sLineBreak, Context.LoggedUser.Roles.ToArray));
+ RenderResponseStream;
+end;
+
+procedure TAdminController.OnlyRole1EmittingJSON;
+begin
+ ContentType := TMVCMediaType.APPLICATION_JSON;
+ Render('This is protected content accessible only by user1: parameter = ' +
+ Context.Request.Params['par1']);
+end;
+
+procedure TAdminController.OnlyRole2;
+begin
+ ContentType := TMVCMediaType.TEXT_PLAIN;
+ ResponseStream.AppendLine('Hey! Hello ' + Context.LoggedUser.UserName +
+ ', now you are a logged user and this is a protected content!');
+ ResponseStream.AppendLine('As logged user you have the following roles: ' +
+ sLineBreak + string.Join(sLineBreak, Context.LoggedUser.Roles.ToArray));
+ RenderResponseStream;
+end;
+
+end.
diff --git a/samples/authenticationauthorization/AuthenticateAuthorize.dpr b/samples/middleware_basicauthentication/AuthenticateAuthorize.dpr
similarity index 96%
rename from samples/authenticationauthorization/AuthenticateAuthorize.dpr
rename to samples/middleware_basicauthentication/AuthenticateAuthorize.dpr
index ef11620c..fd538d1e 100644
--- a/samples/authenticationauthorization/AuthenticateAuthorize.dpr
+++ b/samples/middleware_basicauthentication/AuthenticateAuthorize.dpr
@@ -1,53 +1,53 @@
-program AuthenticateAuthorize;
-
-{$APPTYPE CONSOLE}
-
-uses
- System.SysUtils,
-{$IFDEF MSWINDOWS}
- Winapi.Windows,
- Winapi.ShellAPI,
-{$ENDIF}
- Web.WebReq,
- Web.WebBroker,
- IdHTTPWebBrokerBridge,
- WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule} ,
- AppControllerU in 'AppControllerU.pas',
- MVCFramework.Middleware.Authentication
- in '..\..\sources\MVCFramework.Middleware.Authentication.pas',
- AuthenticationU in 'AuthenticationU.pas';
-
-{$R *.res}
-
-procedure RunServer(APort: Integer);
-var
- LServer: TIdHTTPWebBrokerBridge;
-begin
- Writeln(Format('Starting HTTP Server or port %d', [APort]));
- LServer := TIdHTTPWebBrokerBridge.Create(nil);
- try
- LServer.DefaultPort := APort;
- LServer.Active := True;
- Writeln('Press RETURN to stop the server');
- {$IFDEF MSWINDOWS}
- ShellExecute(0, 'open', PChar('http://localhost:' + IntToStr(APort) + '/static'), nil, nil, SW_SHOW);
- {$ENDIF}
- ReadLn;
- finally
- LServer.Free;
- end;
-end;
-
-begin
- ReportMemoryLeaksOnShutdown := True;
- try
- if WebRequestHandler <> nil then
- WebRequestHandler.WebModuleClass := WebModuleClass;
- WebRequestHandlerProc.MaxConnections := 1024;
- RunServer(8080);
- except
- on E: Exception do
- Writeln(E.ClassName, ': ', E.Message);
- end
-
-end.
+program AuthenticateAuthorize;
+
+{$APPTYPE CONSOLE}
+
+uses
+ System.SysUtils,
+{$IFDEF MSWINDOWS}
+ Winapi.Windows,
+ Winapi.ShellAPI,
+{$ENDIF}
+ Web.WebReq,
+ Web.WebBroker,
+ IdHTTPWebBrokerBridge,
+ WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule} ,
+ AppControllerU in 'AppControllerU.pas',
+ MVCFramework.Middleware.Authentication
+ in '..\..\sources\MVCFramework.Middleware.Authentication.pas',
+ AuthenticationU in 'AuthenticationU.pas';
+
+{$R *.res}
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln(Format('Starting HTTP Server or port %d', [APort]));
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.DefaultPort := APort;
+ LServer.Active := True;
+ Writeln('Press RETURN to stop the server');
+ {$IFDEF MSWINDOWS}
+ ShellExecute(0, 'open', PChar('http://localhost:' + IntToStr(APort) + '/static'), nil, nil, SW_SHOW);
+ {$ENDIF}
+ ReadLn;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ ReportMemoryLeaksOnShutdown := True;
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+ WebRequestHandlerProc.MaxConnections := 1024;
+ RunServer(8080);
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end
+
+end.
diff --git a/samples/authenticationauthorization/AuthenticateAuthorize.dproj b/samples/middleware_basicauthentication/AuthenticateAuthorize.dproj
similarity index 75%
rename from samples/authenticationauthorization/AuthenticateAuthorize.dproj
rename to samples/middleware_basicauthentication/AuthenticateAuthorize.dproj
index 30387c68..4d73eccc 100644
--- a/samples/authenticationauthorization/AuthenticateAuthorize.dproj
+++ b/samples/middleware_basicauthentication/AuthenticateAuthorize.dproj
@@ -1,1180 +1,907 @@
-
-
- {7B54055A-5749-4136-9FE2-35FDBEEA874C}
- 19.1
- VCL
- AuthenticateAuthorize.dpr
- True
- Debug
- Win32
- 1
- Console
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- $(BDS)\bin\delphi_PROJECTICNS.icns
- AuthenticateAuthorize
- ..\..\sources;..\..\lib\delphistompclient;..\..\lib\loggerpro;..\..\lib\dmustache;$(DCC_UnitSearchPath)
- CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
- None
- 1040
- $(BDS)\bin\delphi_PROJECTICON.ico
- System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
-
-
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- 1033
- cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;JvDotNetCtrls;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;JvXPCtrls;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;FMXfrx17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;CloudService;dxPScxCommonRS17;FmxTeeUI;frxDB17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;JvRuntimeDesign;dxPScxVGridLnkRS17;JclDeveloperTools;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;MyFrameTestPackage;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;fs17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;DataBindingsVCL170;dxSkinOffice2010SilverRS17;vcldbx;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DataBindings;DBXOdbcDriver;IcsCommonDXE3Run;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;FMXTee;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;Jcl;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;Intraweb;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;fsDB17;inet;dorm_runtime_xe3;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;inetdbbde;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;MetropolisUILiveTile;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;vclribbon;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;CodeSiteExpressPkg;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;JvDocking;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;frx17;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;JclContainers;NxAddonsRun_dxe3;CPortLibDXE;JvSystem;dxorgcRS17;svnui;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;FMXfrxDB17;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;JclVcl;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;frxe17;svn;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;bdertl;VirtualTreesR;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
-
-
- cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;dxPScxCommonRS17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;dxPScxVGridLnkRS17;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;dxSkinOffice2010SilverRS17;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DBXOdbcDriver;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;inet;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;NxAddonsRun_dxe3;JvSystem;dxorgcRS17;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- 3
- true
- 1033
- false
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- 1033
-
-
-
- MainSource
-
-
-
- TWebModule
-
-
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
-
-
-
-
- False
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- False
- 1040
- 1252
-
-
-
-
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
-
-
-
-
-
-
-
-
-
- AuthenticateAuthorize.dpr
-
-
- Embarcadero C++Builder Office 2000 Servers Package
- Embarcadero C++Builder Office XP Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
- FastReport 6.0 Tee Components
-
-
-
-
-
- AuthenticateAuthorize.exe
- true
-
-
-
-
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- 1
- .framework
-
-
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- False
-
-
- 12
-
-
-
-
-
+
+
+ {7B54055A-5749-4136-9FE2-35FDBEEA874C}
+ 19.5
+ VCL
+ AuthenticateAuthorize.dpr
+ True
+ Debug
+ Win32
+ 1
+ Console
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ AuthenticateAuthorize
+ ..\..\sources;..\..\lib\delphistompclient;..\..\lib\loggerpro;..\..\lib\dmustache;$(DCC_UnitSearchPath)
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ None
+ 1040
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ .\$(Platform)\$(Config)
+ .\bin
+ false
+ false
+ false
+ false
+ false
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ 1033
+ cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;JvDotNetCtrls;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;JvXPCtrls;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;FMXfrx17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;CloudService;dxPScxCommonRS17;FmxTeeUI;frxDB17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;JvRuntimeDesign;dxPScxVGridLnkRS17;JclDeveloperTools;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;MyFrameTestPackage;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;fs17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;DataBindingsVCL170;dxSkinOffice2010SilverRS17;vcldbx;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DataBindings;DBXOdbcDriver;IcsCommonDXE3Run;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;FMXTee;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;Jcl;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;Intraweb;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;fsDB17;inet;dorm_runtime_xe3;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;inetdbbde;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;MetropolisUILiveTile;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;vclribbon;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;CodeSiteExpressPkg;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;JvDocking;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;frx17;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;JclContainers;NxAddonsRun_dxe3;CPortLibDXE;JvSystem;dxorgcRS17;svnui;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;FMXfrxDB17;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;JclVcl;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;frxe17;svn;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;bdertl;VirtualTreesR;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
+
+
+ cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;dxPScxCommonRS17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;dxPScxVGridLnkRS17;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;dxSkinOffice2010SilverRS17;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DBXOdbcDriver;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;inet;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;NxAddonsRun_dxe3;JvSystem;dxorgcRS17;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ 3
+ true
+ 1033
+ false
+ none
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ 1033
+
+
+
+ MainSource
+
+
+
+ TWebModule
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ False
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1040
+ 1252
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+
+
+
+
+
+
+ AuthenticateAuthorize.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+
+
+
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 64
+
+
+ classes
+ 64
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ 1
+ .framework
+
+
+ 1
+ .framework
+
+
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/samples/authenticationauthorization/AuthenticationU.pas b/samples/middleware_basicauthentication/AuthenticationU.pas
similarity index 96%
rename from samples/authenticationauthorization/AuthenticationU.pas
rename to samples/middleware_basicauthentication/AuthenticationU.pas
index cc6737d2..0f5f1bf3 100644
--- a/samples/authenticationauthorization/AuthenticationU.pas
+++ b/samples/middleware_basicauthentication/AuthenticationU.pas
@@ -1,80 +1,80 @@
-unit AuthenticationU;
-
-interface
-
-uses
- System.SysUtils, MVCFramework.Commons, System.Generics.Collections,
- MVCFramework;
-
-type
- TAuthenticationSample = class(TInterfacedObject, IMVCAuthenticationHandler)
- protected
- procedure OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
- const ActionName: string; var AuthenticationRequired: Boolean);
- procedure OnAuthentication(const AContext: TWebContext; const UserName: string; const Password: string;
- UserRoles: System.Generics.Collections.TList;
- var IsValid: Boolean; const SessionData: TSessionData);
- procedure OnAuthorization(const AContext: TWebContext; UserRoles
- : System.Generics.Collections.TList;
- const ControllerQualifiedClassName: string; const ActionName: string;
- var IsAuthorized: Boolean);
- end;
-
-implementation
-
-{ TMVCAuthorization }
-
-procedure TAuthenticationSample.OnAuthentication(const AContext: TWebContext; const UserName: string;
- const Password: string;
- UserRoles: System.Generics.Collections.TList;
- var IsValid: Boolean; const SessionData: TSessionData);
-begin
- IsValid := UserName.Equals(Password); // hey!, this is just a demo!!!
- if IsValid then
- begin
- if UserName = 'user1' then
- begin
- UserRoles.Add('role1');
- end;
- if UserName = 'user2' then
- begin
- UserRoles.Add('role2');
- end;
- if UserName = 'user3' then // all the roles
- begin
- UserRoles.Add('role1');
- UserRoles.Add('role2');
- end;
- end
- else
- begin
- UserRoles.Clear;
- end;
-end;
-
-procedure TAuthenticationSample.OnAuthorization
- (const AContext: TWebContext; UserRoles
- : System.Generics.Collections.TList;
- const ControllerQualifiedClassName: string; const ActionName: string;
- var IsAuthorized: Boolean);
-begin
- IsAuthorized := False;
- if ActionName = 'Logout' then
- IsAuthorized := True; // you can always call logout
- if ActionName = 'OnlyRole2' then
- IsAuthorized := UserRoles.Contains('role2');
- if ActionName = 'OnlyRole1' then
- IsAuthorized := UserRoles.Contains('role1');
- if ActionName = 'OnlyRole1EmittingJSON' then
- IsAuthorized := UserRoles.Contains('role1');
-end;
-
-procedure TAuthenticationSample.OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
- const ActionName: string; var AuthenticationRequired: Boolean);
-begin
- AuthenticationRequired := ControllerQualifiedClassName =
- 'AppControllerU.TAdminController';
-
-end;
-
-end.
+unit AuthenticationU;
+
+interface
+
+uses
+ System.SysUtils, MVCFramework.Commons, System.Generics.Collections,
+ MVCFramework;
+
+type
+ TAuthenticationSample = class(TInterfacedObject, IMVCAuthenticationHandler)
+ protected
+ procedure OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
+ const ActionName: string; var AuthenticationRequired: Boolean);
+ procedure OnAuthentication(const AContext: TWebContext; const UserName: string; const Password: string;
+ UserRoles: System.Generics.Collections.TList;
+ var IsValid: Boolean; const SessionData: TSessionData);
+ procedure OnAuthorization(const AContext: TWebContext; UserRoles
+ : System.Generics.Collections.TList;
+ const ControllerQualifiedClassName: string; const ActionName: string;
+ var IsAuthorized: Boolean);
+ end;
+
+implementation
+
+{ TMVCAuthorization }
+
+procedure TAuthenticationSample.OnAuthentication(const AContext: TWebContext; const UserName: string;
+ const Password: string;
+ UserRoles: System.Generics.Collections.TList;
+ var IsValid: Boolean; const SessionData: TSessionData);
+begin
+ IsValid := UserName.Equals(Password); // hey!, this is just a demo!!!
+ if IsValid then
+ begin
+ if UserName = 'user1' then
+ begin
+ UserRoles.Add('role1');
+ end;
+ if UserName = 'user2' then
+ begin
+ UserRoles.Add('role2');
+ end;
+ if UserName = 'user3' then // all the roles
+ begin
+ UserRoles.Add('role1');
+ UserRoles.Add('role2');
+ end;
+ end
+ else
+ begin
+ UserRoles.Clear;
+ end;
+end;
+
+procedure TAuthenticationSample.OnAuthorization
+ (const AContext: TWebContext; UserRoles
+ : System.Generics.Collections.TList;
+ const ControllerQualifiedClassName: string; const ActionName: string;
+ var IsAuthorized: Boolean);
+begin
+ IsAuthorized := False;
+ if ActionName = 'Logout' then
+ IsAuthorized := True; // you can always call logout
+ if ActionName = 'OnlyRole2' then
+ IsAuthorized := UserRoles.Contains('role2');
+ if ActionName = 'OnlyRole1' then
+ IsAuthorized := UserRoles.Contains('role1');
+ if ActionName = 'OnlyRole1EmittingJSON' then
+ IsAuthorized := UserRoles.Contains('role1');
+end;
+
+procedure TAuthenticationSample.OnRequest(const AContext: TWebContext; const ControllerQualifiedClassName: string;
+ const ActionName: string; var AuthenticationRequired: Boolean);
+begin
+ AuthenticationRequired := ControllerQualifiedClassName =
+ 'AppControllerU.TAdminController';
+
+end;
+
+end.
diff --git a/samples/authenticationauthorization/ProjectGroup1.groupproj b/samples/middleware_basicauthentication/ProjectGroup.groupproj
similarity index 100%
rename from samples/authenticationauthorization/ProjectGroup1.groupproj
rename to samples/middleware_basicauthentication/ProjectGroup.groupproj
diff --git a/samples/authenticationauthorization/WebModuleUnit1.dfm b/samples/middleware_basicauthentication/WebModuleUnit1.dfm
similarity index 84%
rename from samples/authenticationauthorization/WebModuleUnit1.dfm
rename to samples/middleware_basicauthentication/WebModuleUnit1.dfm
index b43b8558..2c58d387 100644
--- a/samples/authenticationauthorization/WebModuleUnit1.dfm
+++ b/samples/middleware_basicauthentication/WebModuleUnit1.dfm
@@ -1,12 +1,11 @@
-object WebModule1: TWebModule1
- OldCreateOrder = False
- OnCreate = WebModuleCreate
- Actions = <
- item
- Default = True
- Name = 'DefaultHandler'
- PathInfo = '/'
- end>
- Height = 230
- Width = 415
-end
+object WebModule1: TWebModule1
+ OnCreate = WebModuleCreate
+ Actions = <
+ item
+ Default = True
+ Name = 'DefaultHandler'
+ PathInfo = '/'
+ end>
+ Height = 230
+ Width = 415
+end
diff --git a/samples/authenticationauthorization/WebModuleUnit1.pas b/samples/middleware_basicauthentication/WebModuleUnit1.pas
similarity index 87%
rename from samples/authenticationauthorization/WebModuleUnit1.pas
rename to samples/middleware_basicauthentication/WebModuleUnit1.pas
index 146a9bd1..addec183 100644
--- a/samples/authenticationauthorization/WebModuleUnit1.pas
+++ b/samples/middleware_basicauthentication/WebModuleUnit1.pas
@@ -1,58 +1,60 @@
-unit WebModuleUnit1;
-
-interface
-
-uses
- System.SysUtils,
- System.Classes,
- Web.HTTPApp,
- MVCFramework,
- MVCFramework.Commons;
-
-type
- TWebModule1 = class(TWebModule)
- procedure WebModuleCreate(Sender: TObject);
-
- private
- MVC: TMVCEngine;
-
- public
- { Public declarations }
- end;
-
-var
- WebModuleClass: TComponentClass = TWebModule1;
-
-implementation
-
-{$R *.dfm}
-
-
-uses
- AppControllerU,
- System.Generics.Collections,
- MVCFramework.Middleware.Authentication,
- MVCFramework.Middleware.StaticFiles,
- AuthenticationU;
-
-procedure TWebModule1.WebModuleCreate(Sender: TObject);
-begin
- MVC := TMVCEngine.Create(Self,
- procedure(Config: TMVCConfig)
- begin
- Config[TMVCConfigKey.SessionTimeout] := '30';
- Config[TMVCConfigKey.DefaultContentType] := 'text/html';
- end);
- MVC
- .AddController(TApp1MainController)
- .AddController(TAdminController)
- .AddMiddleware(TMVCBasicAuthenticationMiddleware.Create(TAuthenticationSample.Create))
- .AddMiddleware(TMVCStaticFilesMiddleware.Create(
- '/static', { StaticFilesPath }
- '..\..\www', { DocumentRoot }
- 'index.html',
- False { not serving a SPA }
- ));
-end;
-
-end.
+unit WebModuleUnit1;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ Web.HTTPApp,
+ MVCFramework,
+ MVCFramework.Commons, FireDAC.Phys.PGDef, FireDAC.Stan.Intf, FireDAC.Phys,
+ FireDAC.Phys.PG;
+
+type
+ TWebModule1 = class(TWebModule)
+ procedure WebModuleCreate(Sender: TObject);
+
+ private
+ MVC: TMVCEngine;
+
+ public
+ { Public declarations }
+ end;
+
+var
+ WebModuleClass: TComponentClass = TWebModule1;
+
+implementation
+
+{$R *.dfm}
+
+
+uses
+ AppControllerU,
+ System.Generics.Collections,
+ MVCFramework.Middleware.Authentication,
+ MVCFramework.Middleware.ActiveRecord,
+ MVCFramework.Middleware.StaticFiles,
+ AuthenticationU;
+
+procedure TWebModule1.WebModuleCreate(Sender: TObject);
+begin
+ MVC := TMVCEngine.Create(Self,
+ procedure(Config: TMVCConfig)
+ begin
+ Config[TMVCConfigKey.SessionTimeout] := '30';
+ Config[TMVCConfigKey.DefaultContentType] := 'text/html';
+ end);
+ MVC
+ .AddController(TApp1MainController)
+ .AddController(TAdminController)
+ .AddMiddleware(TMVCBasicAuthenticationMiddleware.Create(TAuthenticationSample.Create))
+ .AddMiddleware(TMVCStaticFilesMiddleware.Create(
+ '/static', { StaticFilesPath }
+ 'www', { DocumentRoot }
+ 'index.html',
+ False { not serving a SPA }
+ ));
+end;
+
+end.
diff --git a/samples/authenticationauthorization/www/index.html b/samples/middleware_basicauthentication/bin/www/index.html
similarity index 96%
rename from samples/authenticationauthorization/www/index.html
rename to samples/middleware_basicauthentication/bin/www/index.html
index d95da22f..e79e5c34 100644
--- a/samples/authenticationauthorization/www/index.html
+++ b/samples/middleware_basicauthentication/bin/www/index.html
@@ -1,18 +1,18 @@
-
-
- Here's the public and the private sections on this application server
-
-
- The available users are shown below:
-
- - user1/user1 (role1)
- - user2/user2 (role2)
- - user3/user3 (role1, role2)
-
-
-
+
+
+ Here's the public and the private sections on this application server
+
+
+ The available users are shown below:
+
+ - user1/user1 (role1)
+ - user2/user2 (role2)
+ - user3/user3 (role1, role2)
+
+
+
\ No newline at end of file
diff --git a/samples/authenticationauthorization/vclclient/AuthenticationAuthorizationClient.dpr b/samples/middleware_basicauthentication/vclclient/AuthenticationAuthorizationClient.dpr
similarity index 100%
rename from samples/authenticationauthorization/vclclient/AuthenticationAuthorizationClient.dpr
rename to samples/middleware_basicauthentication/vclclient/AuthenticationAuthorizationClient.dpr
diff --git a/samples/authenticationauthorization/vclclient/AuthenticationAuthorizationClient.dproj b/samples/middleware_basicauthentication/vclclient/AuthenticationAuthorizationClient.dproj
similarity index 77%
rename from samples/authenticationauthorization/vclclient/AuthenticationAuthorizationClient.dproj
rename to samples/middleware_basicauthentication/vclclient/AuthenticationAuthorizationClient.dproj
index fda121a9..87a5b116 100644
--- a/samples/authenticationauthorization/vclclient/AuthenticationAuthorizationClient.dproj
+++ b/samples/middleware_basicauthentication/vclclient/AuthenticationAuthorizationClient.dproj
@@ -1,7 +1,7 @@
{E7317702-64D3-4A65-8734-030F3AE3DBBC}
- 19.1
+ 19.5
VCL
AuthenticationAuthorizationClient.dpr
True
@@ -68,7 +68,8 @@
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
1033
DBXSqliteDriver;DBXDb2Driver;dxCoreRS23;vclactnband;frxe23;vclFireDAC;dxPSLnksRS23;dxPSdxLCLnkRS23;tethering;cxDataRS23;dxPSdxOCLnkRS23;dxTabbedMDIRS23;FireDACADSDriver;dxSkinBlackRS23;dxSkinLondonLiquidSkyRS23;JvPluginSystem;dxDBXServerModeRS23;dxHttpIndyRequestRS23;dxPScxGridLnkRS23;cxSchedulerRS23;FireDACMSSQLDriver;dclRBDBE1723;vcltouch;JvBands;vcldb;rbDB1723;svn;dxWizardControlRS23;dxSkinMcSkinRS23;dxPScxCommonRS23;JvJans;Intraweb;dxSkinOffice2007BlueRS23;rbIBE1723;dxBarRS23;cxSchedulerRibbonStyleEventEditorRS23;dxSkinOffice2013WhiteRS23;JvDotNetCtrls;dxPSTeeChartRS23;cxLibraryRS23;dxSkinVisualStudio2013LightRS23;vclib;cxPivotGridChartRS23;rbDBE1723;dxSkinSummer2008RS23;dxPSdxDBOCLnkRS23;dxGDIPlusRS23;dxSkinDarkSideRS23;FireDACDBXDriver;dxSkinFoggyRS23;dxSkinSevenRS23;vclx;rbCIDE1723;dxSkinOffice2010SilverRS23;dxdborRS23;RESTBackendComponents;dxLayoutControlRS23;dxPSPrVwRibbonRS23;VCLRESTComponents;dxSkinDevExpressStyleRS23;dxSkinWhiteprintRS23;vclie;bindengine;CloudService;rbRAP1723;JvHMI;FireDACMySQLDriver;dxSkinOffice2013DarkGrayRS23;DataSnapClient;dxPScxPCProdRS23;bindcompdbx;DBXSybaseASEDriver;IndyIPServer;dxSkinPumpkinRS23;IndySystem;dsnapcon;cxTreeListdxBarPopupMenuRS23;dclRBIBE1723;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;dxSkinLilianRS23;Jcl;rbADO1723;dxBarDBNavRS23;dxFlowChartRS23;dxSkinOffice2016ColorfulRS23;rbUSER1723;DBXOdbcDriver;FireDACTDataDriver;FMXTee;ipstudiowinclient;soaprtl;DbxCommonDriver;dxSpreadSheetRS23;AsyncProDR;JvManagedThreads;dxSkinOffice2007PinkRS23;dxPSdxSpreadSheetLnkRS23;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;DTKANPRPackage;dxSkinHighContrastRS23;rtl;dxSkinSevenClassicRS23;DbxClientDriver;dxSkinDevExpressDarkStyleRS23;DBXSybaseASADriver;dxNavBarRS23;dxSkinMetropolisDarkRS23;CodeSiteExpressPkg;dxSkinTheAsphaltWorldRS23;JvSystem;SampleListViewMultiDetailAppearancePackage;dxRichEditControlRS23;JvStdCtrls;JvTimeFramework;ipstudiowin;appanalytics;cxPivotGridRS23;rbUSERDesign1723;dxSkinsdxDLPainterRS23;IndyIPClient;dxRibbonRS23;dxPScxVGridLnkRS23;bindcompvcl;frxDB23;vcldbx;dxSkinOffice2007SilverRS23;dxPScxTLLnkRS23;dxMapControlRS23;TeeUI;rbDIDE1723;JvPascalInterpreter;JvDocking;VclSmp;dxPScxSchedulerLnkRS23;cxTreeListRS23;FireDACODBCDriver;JclVcl;DataSnapIndy10ServerTransport;dxRibbonCustomizationFormRS23;dxPSRichEditControlLnkRS23;dxBarExtDBItemsRS23;DataSnapProviderClient;FireDACMongoDBDriver;dxSkiniMaginaryRS23;frx23;dxSpellCheckerRS23;JvControls;dxSkinsdxBarPainterRS23;JvPrintPreview;dxSkinCoffeeRS23;DataSnapServerMidas;RESTComponents;DBXInterBaseDriver;rbRTL1723;dxADOServerModeRS23;emsclientfiredac;DataSnapFireDAC;svnui;dxmdsRS23;dxSkinLiquidSkyRS23;dxdbtrRS23;dxSkinSpringTimeRS23;dxPSDBTeeChartRS23;JvGlobus;dxSkinscxPCPainterRS23;dxPSCoreRS23;DBXMSSQLDriver;JvMM;dxSkinXmas2008BlueRS23;rbDAD1723;DatasnapConnectorsFreePascal;bindcompfmx;JvNet;DBXOracleDriver;dxSkinSilverRS23;dxSkinValentineRS23;inetdb;JvAppFrm;ipstudiowinwordxp;rbTC1723;FmxTeeUI;dxBarExtItemsRS23;FireDACIBDriver;fmx;fmxdae;DelphiCookbookListViewAppearance;dxServerModeRS23;dxPsPrVwAdvRS23;dxSkinOffice2010BlackRS23;JvWizards;cxPageControlRS23;dxSkinStardustRS23;cxSchedulerGridRS23;dbexpress;IndyCore;dxSkinSharpPlusRS23;UIBD21Win32R;JvPageComps;dsnap;DataSnapCommon;emsclient;FireDACCommon;dxSkinOffice2010BlueRS23;bdertl;JvDB;dxSkinVS2010RS23;dxSkinMetropolisRS23;DataSnapConnectors;cxVerticalGridRS23;soapserver;dxSkinCaramelRS23;frxTee23;dxTileControlRS23;JclDeveloperTools;cxGridRS23;CPortLibDXE;FireDACOracleDriver;DBXMySQLDriver;JvCmp;rbFireDAC1723;DBXFirebirdDriver;FireDACCommonDriver;rbTCUI1723;LockBoxDR;inet;IndyIPCommon;JvCustom;dxSkinDarkRoomRS23;dxDockingRS23;vcl;dxSkinOffice2007GreenRS23;dxPScxExtCommonRS23;JvXPCtrls;dxSkinsCoreRS23;FireDACDb2Driver;dxThemeRS23;dxSkinsdxRibbonPainterRS23;dxSkinVisualStudio2013BlueRS23;rbRest1723;TSG5201;dxSkinMoneyTwinsRS23;dxPSdxFCLnkRS23;dxtrmdRS23;TeeDB;FireDAC;cxSchedulerTreeBrowserRS23;JvCore;dxFireDACServerModeRS23;dxSkinBlueRS23;OverbyteIcsD10SRun;JvCrypt;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;cxEditorsRS23;dxSkinGlassOceansRS23;JvDlgs;JvRuntimeDesign;dxSkinsdxNavBarPainterRS23;dxGaugeControlRS23;ibxpress;Tee;dxSkinSharpRS23;DataSnapServer;ibxbindings;cxPivotGridOLAPRS23;rbIDE1723;vclwinx;FireDACDSDriver;dxSkinBlueprintRS23;dxSkinOffice2007BlackRS23;CustomIPTransport;vcldsnap;rbBDE1723;dxSkinOffice2013LightGrayRS23;bindcomp;DBXInformixDriver;officeXPrt;dxPSdxGaugeControlLnkRS23;dxPScxPivotGridLnkRS23;dxorgcRS23;dxPSdxDBTVLnkRS23;dclRBADO1723;vclribbon;dbxcds;KernowSoftwareFMX;adortl;dclRBFireDAC1723;dclRBE1723;dxComnRS23;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;cxExportRS23;dxSkinOffice2016DarkRS23;JclContainers;dxSkinVisualStudio2013DarkRS23;rbRCL1723;dxSkinscxSchedulerPainterRS23;rbRIDE1723;fmxase;$(DCC_UsePackage)
- CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName)
+ ..\bin
+ none
$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
@@ -87,9 +88,7 @@
Debug
true
1033
- true
false
- CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName)
PerMonitor
@@ -110,10 +109,6 @@
dfm
-
- Cfg_2
- Base
-
Base
@@ -121,6 +116,10 @@
Cfg_1
Base
+
+ Cfg_2
+ Base
+
Delphi.Personality.12
@@ -131,19 +130,14 @@
AuthenticationAuthorizationClient.dpr
- Embarcadero C++Builder Office 2000 Servers Package
- Embarcadero C++Builder Office XP Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
-
-
-
- AuthenticationAuthorizationClient.exe
- true
-
-
+
+
1
@@ -156,14 +150,14 @@
0
-
+
classes
- 1
+ 64
classes
- 1
+ 64
@@ -208,7 +202,6 @@
1
-
library\lib\armeabi-v7a
@@ -285,6 +278,16 @@
1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
res\drawable-ldpi
@@ -448,6 +451,11 @@
1
.framework
+
+ Contents\MacOS
+ 1
+ .framework
+
0
@@ -461,7 +469,7 @@
1
.dylib
-
+
1
.dylib
@@ -475,6 +483,11 @@
1
.dylib
+
+ Contents\MacOS
+ 1
+ .dylib
+
0
.dll;.bpl
@@ -489,7 +502,7 @@
1
.dylib
-
+
1
.dylib
@@ -503,6 +516,11 @@
1
.dylib
+
+ Contents\MacOS
+ 1
+ .dylib
+
0
.bpl
@@ -521,7 +539,7 @@
0
-
+
0
@@ -532,512 +550,12 @@
Contents\Resources\StartUp\
0
-
+
+ Contents\Resources\StartUp\
0
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
-
-
- ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
- 1
+
+ 0
@@ -1048,71 +566,15 @@
1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).launchscreen
- 64
-
-
- ..\$(PROJECTNAME).launchscreen
- 64
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
1
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
@@ -1123,6 +585,10 @@
..\
1
+
+ ..\
+ 1
+
@@ -1133,6 +599,10 @@
Contents
1
+
+ Contents
+ 1
+
@@ -1143,6 +613,10 @@
Contents\Resources
1
+
+ Contents\Resources
+ 1
+
@@ -1159,7 +633,7 @@
1
-
+
1
@@ -1173,6 +647,10 @@
Contents\MacOS
1
+
+ Contents\MacOS
+ 1
+
0
@@ -1191,6 +669,66 @@
1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
Assets
@@ -1211,16 +749,218 @@
1
-
-
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
-
+
+
+
-
-
-
+
+
+
True
diff --git a/samples/authenticationauthorization/vclclient/MainClientFormU.dfm b/samples/middleware_basicauthentication/vclclient/MainClientFormU.dfm
similarity index 100%
rename from samples/authenticationauthorization/vclclient/MainClientFormU.dfm
rename to samples/middleware_basicauthentication/vclclient/MainClientFormU.dfm
diff --git a/samples/authenticationauthorization/vclclient/MainClientFormU.pas b/samples/middleware_basicauthentication/vclclient/MainClientFormU.pas
similarity index 100%
rename from samples/authenticationauthorization/vclclient/MainClientFormU.pas
rename to samples/middleware_basicauthentication/vclclient/MainClientFormU.pas
diff --git a/samples/middleware_cors/MainControllerU.pas b/samples/middleware_cors/MainControllerU.pas
new file mode 100644
index 00000000..f386654f
--- /dev/null
+++ b/samples/middleware_cors/MainControllerU.pas
@@ -0,0 +1,30 @@
+unit MainControllerU;
+
+interface
+
+uses
+ MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons;
+
+type
+
+ [MVCPath('/api')]
+ TMyController = class(TMVCController)
+ public
+ [MVCPath('/customers')]
+ [MVCHTTPMethod([httpPOST])]
+ procedure CreateCustomer(const [MVCFromBody] Dict: TMVCStringDictionary);
+ end;
+
+implementation
+
+uses
+ System.SysUtils, MVCFramework.Logger, System.StrUtils;
+
+procedure TMyController.CreateCustomer(const [MVCFromBody] Dict: TMVCStringDictionary);
+begin
+ Render(
+ ObjectDict().Add('data', StrDict.Add('message', Dict['hello']))
+ )
+end;
+
+end.
diff --git a/samples/middleware_cors/ProjectGroup.groupproj b/samples/middleware_cors/ProjectGroup.groupproj
new file mode 100644
index 00000000..1b15a52f
--- /dev/null
+++ b/samples/middleware_cors/ProjectGroup.groupproj
@@ -0,0 +1,48 @@
+
+
+ {9F8DA910-24A1-4497-AAB9-7BDE0D4186C2}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/middleware_cors/SimpleWebServer/SimpleWebServer.dpr b/samples/middleware_cors/SimpleWebServer/SimpleWebServer.dpr
new file mode 100644
index 00000000..ecf31502
--- /dev/null
+++ b/samples/middleware_cors/SimpleWebServer/SimpleWebServer.dpr
@@ -0,0 +1,90 @@
+program SimpleWebServer;
+
+{$APPTYPE CONSOLE}
+
+uses
+ System.SysUtils,
+ WinAPI.ShellAPI,
+ MVCFramework,
+ MVCFramework.Logger,
+ MVCFramework.DotEnv,
+ MVCFramework.Commons,
+ MVCFramework.Signal,
+ Web.ReqMulti,
+ Web.WebReq,
+ Web.WebBroker,
+ IdContext,
+ IdHTTPWebBrokerBridge,
+ WebModuleU in 'WebModuleU.pas', Winapi.Windows {MyWebModule: TWebModule};
+
+{$R *.res}
+
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
+ LServer.DefaultPort := APort;
+ LServer.KeepAlive := True;
+ LServer.MaxConnections := dotEnv.Env('dmvc.webbroker.max_connections', 0);
+ LServer.ListenQueue := dotEnv.Env('dmvc.indy.listen_queue', 500);
+
+ LServer.Active := True;
+
+ { Comment the next line to avoid the default browser startup }
+{$IFDEF MSWINDOWS}
+ ShellExecute(0, 'open', PChar('http://localhost:' + inttostr(APort)), nil, nil, SW_SHOWMAXIMIZED);
+{$ENDIF}
+
+ WriteLn('Simple Web Server');
+ WriteLn('Listening on port ', APort);
+ Write('CTRL+C to shutdown the server');
+ WaitForTerminationSignal;
+ EnterInShutdownState;
+ LServer.Active := False;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ { Enable ReportMemoryLeaksOnShutdown during debug }
+ // ReportMemoryLeaksOnShutdown := True;
+ IsMultiThread := True;
+
+ // DMVCFramework Specific Configuration
+ // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.
+ // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.
+ MVCSerializeNulls := True;
+
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+
+ dotEnvConfigure(
+ function: IMVCDotEnv
+ begin
+ Result := NewDotEnv
+ .WithStrategy(TMVCDotEnvPriority.FileThenEnv)
+ //if available, by default, loads default environment (.env)
+ .UseProfile('test') //if available loads the test environment (.env.test)
+ .UseProfile('prod') //if available loads the prod environment (.env.prod)
+ .UseLogger(procedure(LogItem: String)
+ begin
+ LogW('dotEnv: ' + LogItem);
+ end)
+ .Build(); //uses the executable folder to look for .env* files
+ end);
+
+ WebRequestHandlerProc.MaxConnections := dotEnv.Env('dmvc.handler.max_connections', 1024);
+
+ RunServer(dotEnv.Env('dmvc.server.port', 9090));
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end;
+end.
diff --git a/packages/d112/dmvcframeworkRT.dproj b/samples/middleware_cors/SimpleWebServer/SimpleWebServer.dproj
similarity index 75%
rename from packages/d112/dmvcframeworkRT.dproj
rename to samples/middleware_cors/SimpleWebServer/SimpleWebServer.dproj
index 835fb310..a91e14bf 100644
--- a/packages/d112/dmvcframeworkRT.dproj
+++ b/samples/middleware_cors/SimpleWebServer/SimpleWebServer.dproj
@@ -1,14 +1,14 @@
- {96D17257-AF74-48CB-9893-7BCCB56A069D}
- dmvcframeworkRT.dpk
+ {1553C606-62E3-4D67-8E5B-3440886F90A9}
19.5
None
True
Debug
Win32
1
- Package
+ Console
+ SimpleWebServer.dpr
true
@@ -23,6 +23,11 @@
Base
true
+
+ true
+ Base
+ true
+
true
Base
@@ -51,43 +56,42 @@
.\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
+ ..\bin
false
false
false
false
false
- true
- true
System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- All
- dmvcframeworkRT
- true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ $(DMVC);$(DCC_UnitSearchPath)
+ VCL;$(DCC_Framework)
+ SimpleWebServer
1040
CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- DMVCFramework - CopyRight (2010-2020) Daniele Teti and the DMVCFramework Team
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;fmxase;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;Python;inet;DataSnapCommon;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;Skia.Package.FMX;CustomIPTransport;DBXInterBaseDriver;IndySystem;RadiantShapesFmx;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;FMXTee;DataSnapNativeClient;PythonFmx;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ activity-1.1.0.dex.jar;annotation-1.2.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;biometric-1.1.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.1.0.dex.jar;core-runtime-2.1.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.2.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.2.0.dex.jar;lifecycle-runtime-2.2.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.2.0.dex.jar;lifecycle-viewmodel-savedstate-2.2.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;savedstate-1.0.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+
+
+ DataSnapServer;fmx;emshosting;DbxCommonDriver;bindengine;FireDACCommonODBC;emsclient;FireDACCommonDriver;IndyProtocols;Skia.Package.RTL;RadiantShapesFmx_Design;dbxcds;emsedge;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;dbexpress;FireDACInfxDriver;Python;inet;DataSnapCommon;dbrtl;FireDACOracleDriver;Skia.Package.FMX;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;dsnapxml;DataSnapClient;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;xmlrtl;dsnap;CloudService;FireDACDb2Driver;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ RaizeComponentsVcl;JvNet;vclwinx;DataSnapServer;FixInsight_11;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;frxe28;frxTee28;bindcompvclwinx;Prometheus.Client.Core;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;JvBands;inetdb;JvAppFrm;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;JclVcl;SVGIconImageListFMX;vclactnband;TeeUI;fmxFireDAC;dbexpress;Jcl;JvManagedThreads;FireDACInfxDriver;Python;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;JvPascalInterpreter;PythonVcl;vcltouch;fmxase;frx28;JvPluginSystem;DBXOdbcDriver;DzHTMLText_FMX;dbrtl;JvDB;FireDACDBXDriver;FireDACOracleDriver;ComPortDrv;fmxdae;TeeDB;Skia.Package.FMX;JvTimeFramework;FireDACMSAccDriver;JvCustom;CustomIPTransport;FireDACMSSQLDriver;JvSystem;SVGIconPackage;DataSnapIndy10ServerTransport;JclDeveloperTools;JvControls;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;JvCrypt;FireDACMongoDBDriver;JvJans;JvMM;IndySystem;JvWizards;frxDB28;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;JvGlobus;vcldb;ibxbindings;IconFontsImageList;JclContainers;SynEditDR;JvPageComps;vclFireDAC;JvCore;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;dmvcframeworkDT;bindcompdbx;DzHTMLText_VCL;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;JvDotNetCtrls;JvHMI;DBXSybaseASEDriver;JvRuntimeDesign;DBXDb2Driver;JvXPCtrls;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;JvStdCtrls;ibxpress;JvDlgs;JvDocking;bindcompvcl;dsnap;JvPrintPreview;JvCmp;dmvcframeworkRT;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;IconFontsImageListFMX;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;SVGIconImageList;soapserver;FireDACIBDriver;$(DCC_UsePackage)
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
Debug
- true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
1033
- DMVCFramework - CopyRight (2010-2021) Daniele Teti and the DMVCFramework Team
- rtl;dbrtl;IndySystem;IndyProtocols;IndyCore;dmvcframeworkDT;$(DCC_UsePackage)
- 110
- rtl;dbrtl;IndySystem;IndyProtocols;IndyCore;$(DCC_UsePackage)
+ RaizeComponentsVcl;vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;RadiantShapesFmx_Design;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;SVGIconImageListFMX;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;Python;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;PythonVcl;vcltouch;fmxase;DBXOdbcDriver;DzHTMLText_FMX;dbrtl;FireDACDBXDriver;FireDACOracleDriver;ComPortDrv;fmxdae;TeeDB;Skia.Package.FMX;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;SVGIconPackage;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;RadiantShapesFmx;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;SynEditDR;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;DzHTMLText_VCL;rtl;FireDACMySQLDriver;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;PythonFmx;DatasnapConnectorsFreePascal;soaprtl;SVGIconImageList;soapserver;FireDACIBDriver;$(DCC_UsePackage)
DEBUG;$(DCC_Define)
@@ -96,20 +100,14 @@
true
true
true
+ true
+ true
- true
+ false
1033
- 3
- true
- false
- true
- CompanyName=Daniele Teti and the DMVCFramework Team;FileDescription=DelphiMVCFramework 3.2.2-nitrogen;FileVersion=3.2.2.0;InternalName=DelphiMVCFramework 3.2.2-nitrogen;LegalCopyright=Daniele Teti and the DMVCFramework Team - Apache License 2;LegalTrademarks=DelphiMVCFramework;OriginalFilename=$(MSBuildProjectName);ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=DelphiMVCFramework;ProductVersion=3.2.2;Comments=
- 3
- 2
- 2
- 112
- DMVCFramework - CopyRight (2010-2022) Daniele Teti and the DMVCFramework Team
+ (None)
+ none
false
@@ -121,74 +119,7 @@
MainSource
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
Base
@@ -203,13 +134,15 @@
Delphi.Personality.12
- Package
+ Console
- dmvcframeworkRT.dpk
+ SimpleWebServer.dpr
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
Microsoft Office 2000 Sample Automation Server Wrapper Components
Microsoft Office XP Sample Automation Server Wrapper Components
@@ -225,17 +158,14 @@
true
-
true
-
-
-
+
- dmvcframeworkRT.bpl
+ SimpleWebServer.exe
true
@@ -630,6 +560,127 @@
0
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
@@ -830,133 +881,11 @@
1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
diff --git a/samples/middleware_cors/SimpleWebServer/WebModuleU.dfm b/samples/middleware_cors/SimpleWebServer/WebModuleU.dfm
new file mode 100644
index 00000000..02d66b97
--- /dev/null
+++ b/samples/middleware_cors/SimpleWebServer/WebModuleU.dfm
@@ -0,0 +1,7 @@
+object MyWebModule: TMyWebModule
+ OnCreate = WebModuleCreate
+ OnDestroy = WebModuleDestroy
+ Actions = <>
+ Height = 230
+ Width = 415
+end
diff --git a/samples/middleware_cors/SimpleWebServer/WebModuleU.pas b/samples/middleware_cors/SimpleWebServer/WebModuleU.pas
new file mode 100644
index 00000000..90af30be
--- /dev/null
+++ b/samples/middleware_cors/SimpleWebServer/WebModuleU.pas
@@ -0,0 +1,125 @@
+unit WebModuleU;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ Web.HTTPApp,
+ MVCFramework;
+
+type
+ TMyWebModule = class(TWebModule)
+ procedure WebModuleCreate(Sender: TObject);
+ procedure WebModuleDestroy(Sender: TObject);
+ private
+ FMVC: TMVCEngine;
+ public
+ { Public declarations }
+ end;
+
+var
+ WebModuleClass: TComponentClass = TMyWebModule;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ System.IOUtils,
+ MVCFramework.Commons,
+ MVCFramework.Middleware.ActiveRecord,
+ MVCFramework.Middleware.StaticFiles,
+ MVCFramework.Middleware.Analytics,
+ MVCFramework.Middleware.Redirect,
+ MVCFramework.Middleware.Trace,
+ MVCFramework.Middleware.CORS,
+ MVCFramework.Middleware.ETag,
+ MVCFramework.Middleware.Compression;
+
+procedure TMyWebModule.WebModuleCreate(Sender: TObject);
+begin
+ FMVC := TMVCEngine.Create(Self,
+ procedure(Config: TMVCConfig)
+ begin
+ Config.dotEnv := dotEnv;
+ // session timeout (0 means session cookie)
+ Config[TMVCConfigKey.SessionTimeout] := dotEnv.Env('dmvc.session_timeout', '0');
+ //default content-type
+ Config[TMVCConfigKey.DefaultContentType] := dotEnv.Env('dmvc.default.content_type', TMVCConstants.DEFAULT_CONTENT_TYPE);
+ //default content charset
+ Config[TMVCConfigKey.DefaultContentCharset] := dotEnv.Env('dmvc.default.content_charset', TMVCConstants.DEFAULT_CONTENT_CHARSET);
+ //unhandled actions are permitted?
+ Config[TMVCConfigKey.AllowUnhandledAction] := dotEnv.Env('dmvc.allow_unhandled_actions', 'false');
+ //enables or not system controllers loading (available only from localhost requests)
+ Config[TMVCConfigKey.LoadSystemControllers] := dotEnv.Env('dmvc.load_system_controllers', 'true');
+ //default view file extension
+ Config[TMVCConfigKey.DefaultViewFileExtension] := dotEnv.Env('dmvc.default.view_file_extension', 'html');
+ //view path
+ Config[TMVCConfigKey.ViewPath] := dotEnv.Env('dmvc.view_path', 'templates');
+ //Max Record Count for automatic Entities CRUD
+ Config[TMVCConfigKey.MaxEntitiesRecordCount] := dotEnv.Env('dmvc.max_entities_record_count', IntToStr(TMVCConstants.MAX_RECORD_COUNT));
+ //Enable Server Signature in response
+ Config[TMVCConfigKey.ExposeServerSignature] := dotEnv.Env('dmvc.expose_server_signature', 'false');
+ //Enable X-Powered-By Header in response
+ Config[TMVCConfigKey.ExposeXPoweredBy] := dotEnv.Env('dmvc.expose_x_powered_by', 'true');
+ // Max request size in bytes
+ Config[TMVCConfigKey.MaxRequestSize] := dotEnv.Env('dmvc.max_request_size', IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE));
+ end);
+
+ // Analytics middleware generates a csv log, useful to do traffic analysis
+ //FMVC.AddMiddleware(TMVCAnalyticsMiddleware.Create(GetAnalyticsDefaultLogger));
+
+ // The folder mapped as documentroot for TMVCStaticFilesMiddleware must exists!
+ FMVC.AddMiddleware(
+ TMVCStaticFilesMiddleware.Create(
+ '/static',
+ TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), 'www')));
+
+ FMVC.AddMiddleware(TMVCRedirectMiddleware.Create(['/'], '/static'));
+
+ // Trace middlewares produces a much detailed log for debug purposes
+ //FMVC.AddMiddleware(TMVCTraceMiddleware.Create);
+
+ // CORS middleware handles... well, CORS
+ //FMVC.AddMiddleware(TMVCCORSMiddleware.Create);
+
+ // Simplifies TMVCActiveRecord connection definition
+ {
+ FMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create(
+ dotEnv.Env('firedac.connection_definition_name', 'MyConnDef'),
+ dotEnv.Env('firedac.connection_definitions_filename', 'FDConnectionDefs.ini')
+ ));
+ }
+
+
+ // Compression middleware must be the last in the chain, just before the ETag, if present.
+ //FMVC.AddMiddleware(TMVCCompressionMiddleware.Create);
+
+ // ETag middleware must be the latest in the chain
+ //FMVC.AddMiddleware(TMVCETagMiddleware.Create);
+
+
+
+ {
+ FMVC.OnWebContextCreate(
+ procedure(const Context: TWebContext)
+ begin
+ // Initialize services to make them accessibile from Context
+ // Context.CustomIntfObject := TMyService.Create;
+ end);
+
+ FMVC.OnWebContextDestroy(
+ procedure(const Context: TWebContext)
+ begin
+ //Cleanup services, if needed
+ end);
+ }
+end;
+
+procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
+begin
+ FMVC.Free;
+end;
+
+end.
diff --git a/samples/middleware_cors/WebModuleU.dfm b/samples/middleware_cors/WebModuleU.dfm
new file mode 100644
index 00000000..02d66b97
--- /dev/null
+++ b/samples/middleware_cors/WebModuleU.dfm
@@ -0,0 +1,7 @@
+object MyWebModule: TMyWebModule
+ OnCreate = WebModuleCreate
+ OnDestroy = WebModuleDestroy
+ Actions = <>
+ Height = 230
+ Width = 415
+end
diff --git a/samples/middleware_cors/WebModuleU.pas b/samples/middleware_cors/WebModuleU.pas
new file mode 100644
index 00000000..7e18b01d
--- /dev/null
+++ b/samples/middleware_cors/WebModuleU.pas
@@ -0,0 +1,80 @@
+unit WebModuleU;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ Web.HTTPApp,
+ MVCFramework,
+ MVCFramework.Logger;
+
+type
+ TMyWebModule = class(TWebModule)
+ procedure WebModuleCreate(Sender: TObject);
+ procedure WebModuleDestroy(Sender: TObject);
+ private
+ FMVC: TMVCEngine;
+ public
+ { Public declarations }
+ end;
+
+var
+ WebModuleClass: TComponentClass = TMyWebModule;
+
+implementation
+
+{$R *.dfm}
+
+
+uses
+ MainControllerU,
+ System.IOUtils,
+ MVCFramework.Commons,
+ MVCFramework.Middleware.StaticFiles,
+ MVCFramework.Middleware.Redirect,
+ MVCFramework.Middleware.Compression,
+ MVCFramework.Middleware.CORS;
+
+procedure TMyWebModule.WebModuleCreate(Sender: TObject);
+begin
+ FMVC := TMVCEngine.Create(Self,
+ procedure(Config: TMVCConfig)
+ begin
+ // session timeout (0 means session cookie)
+ Config[TMVCConfigKey.SessionTimeout] := '0';
+ // default content-type
+ Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE;
+ // default content charset
+ Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET;
+ // unhandled actions are permitted?
+ Config[TMVCConfigKey.AllowUnhandledAction] := 'false';
+ // default view file extension
+ Config[TMVCConfigKey.DefaultViewFileExtension] := 'html';
+ // view path
+ Config[TMVCConfigKey.ViewPath] := 'templates';
+ // Max Record Count for automatic Entities CRUD
+ Config[TMVCConfigKey.MaxEntitiesRecordCount] := '20';
+ // Enable Server Signature in response
+ Config[TMVCConfigKey.ExposeServerSignature] := 'true';
+ // Max request size in bytes
+ Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);
+ Config[TMVCConfigKey.LoadSystemControllers] := 'false';
+ end);
+ FMVC
+ .AddController(TMyController);
+
+
+ { // Allows all origins -> * }
+ //FMVC.AddMiddleware(TMVCCORSMiddleware.Create);
+
+ { // Allows all origins -> * }
+ FMVC.AddMiddleware(TMVCCORSMiddleware.Create('https://anotherserver.com,http://localhost:9090'));
+end;
+
+procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
+begin
+ FMVC.Free;
+end;
+
+end.
diff --git a/samples/middleware_cors/bin/www/index.html b/samples/middleware_cors/bin/www/index.html
new file mode 100644
index 00000000..903df5db
--- /dev/null
+++ b/samples/middleware_cors/bin/www/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ DMVCFramework CORS Sample
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/middleware_cors/middleware_cors.dpr b/samples/middleware_cors/middleware_cors.dpr
new file mode 100644
index 00000000..1bbfc40a
--- /dev/null
+++ b/samples/middleware_cors/middleware_cors.dpr
@@ -0,0 +1,67 @@
+program middleware_cors;
+
+{$APPTYPE CONSOLE}
+
+
+uses
+ System.SysUtils,
+ MVCFramework,
+ MVCFramework.Logger,
+ MVCFramework.Commons,
+ {$IFDEF MSWINDOWS}
+ Winapi.Windows,
+ Winapi.ShellAPI,
+ {$ENDIF }
+ MVCFramework.Signal,
+ Web.ReqMulti,
+ Web.WebReq,
+ Web.WebBroker,
+ IdContext,
+ IdHTTPWebBrokerBridge,
+ MainControllerU in 'MainControllerU.pas',
+ WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule};
+
+{$R *.res}
+
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
+
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
+ LServer.DefaultPort := APort;
+ LServer.MaxConnections := 0;
+ LServer.ListenQueue := 200;
+
+ { required if you use JWT middleware }
+ LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
+ LServer.Active := True;
+ WriteLn('Middleware CORS Sample');
+ WriteLn('Listening on port ', APort);
+ Write('CTRL+C to shutdown the server');
+ WaitForTerminationSignal;
+ EnterInShutdownState;
+ LServer.Active := False;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ ReportMemoryLeaksOnShutdown := True;
+ IsMultiThread := True;
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+ WebRequestHandlerProc.MaxConnections := 1024;
+ RunServer(8080);
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end;
+
+end.
diff --git a/packages/d112/dmvcframeworkDT.dproj b/samples/middleware_cors/middleware_cors.dproj
similarity index 79%
rename from packages/d112/dmvcframeworkDT.dproj
rename to samples/middleware_cors/middleware_cors.dproj
index aa8c1caf..7e6ad52e 100644
--- a/packages/d112/dmvcframeworkDT.dproj
+++ b/samples/middleware_cors/middleware_cors.dproj
@@ -1,14 +1,14 @@
- {84344511-1DC2-41BA-8689-9F36C1D475BE}
- dmvcframeworkDT.dpk
+ {A4AB18DC-0F2D-4D2A-94F8-67D871413D88}
19.5
- None
+ VCL
+ middleware_cors.dpr
True
Debug
Win32
1
- Package
+ Console
true
@@ -23,6 +23,11 @@
Base
true
+
+ true
+ Base
+ true
+
true
Base
@@ -49,12 +54,6 @@
Base
true
-
- true
- Cfg_2
- true
- true
-
.\$(Platform)\$(Config)
.\$(Platform)\$(Config)
@@ -63,37 +62,38 @@
false
false
false
- true
- true
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- All
- dmvcframeworkDT
- 1040
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- DelphiMVCFramework IDE Expert
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ $(DMVC);$(DCC_UnitSearchPath)
+ VCL;$(DCC_Framework)
+ middleware_cors
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;tethering;DataSnapFireDAC;bindcompfmx;fmx;FireDACIBDriver;RadiantShapesFmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;ibxbindings;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;RadiantShapesFmx_Design;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
+ DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;tethering;DataSnapFireDAC;bindcompfmx;fmx;FireDACIBDriver;RadiantShapesFmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;ibxbindings;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;RadiantShapesFmx_Design;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+
+
+ RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACADSDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;Spring.Data;inetdb;SMCmpntRX103;emsedge;FireDACIBDriver;dbexpress;IndyCore;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;soapserver;bindengine;CloudService;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndySystem;FireDACDb2Driver;FireDACInfxDriver;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;rtl;emsserverresource;DbxClientDriver;CustomIPTransport;bindcomp;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;IndyProtocols;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)
+ DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;tethering;svnui;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;IconFontsImageList;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;Spring.Data;inetdb;SMCmpntRX103;RaizeComponentsVcl;emsedge;RaizeComponentsVclDb;fmx;FireDACIBDriver;fmxdae;RadiantShapesFmx;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;Python_D;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IconFontsImageListFMX;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;ibxbindings;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dmvcframeworkRT;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;DataSnapIndy10ServerTransport;dmvcframeworkDT;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
Debug
- true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
1033
- rtl;IndySystem;IndyProtocols;IndyCore;dbrtl;dmvcframeworkRT;$(DCC_UsePackage)
- ..\..\sources;$(DCC_UnitSearchPath)
- DelphiMVCFramework 3.x - Design Time Support
- 110
+ .\bin
+ (None)
- rtl;IndySystem;IndyProtocols;IndyCore;dbrtl;$(DCC_UsePackage)
+ DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;tethering;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;Spring.Data;inetdb;RaizeComponentsVcl;emsedge;RaizeComponentsVclDb;fmx;FireDACIBDriver;fmxdae;RadiantShapesFmx;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;ibxbindings;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)
DEBUG;$(DCC_Define)
@@ -105,11 +105,7 @@
false
- true
1033
- false
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=Daniele Teti and the DMVCFramework Team;LegalTrademarks=DelphiMVCFramework;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 112
false
@@ -117,51 +113,15 @@
0
0
-
- true
- 1033
-
MainSource
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ TWebModule
-
-
-
-
-
-
-
-
- ICON
- DMVCNewProjectIcon
-
-
- ICON
- DMVCNewUnitIcon
-
-
- BITMAP
- SplashScreen
-
Base
@@ -176,37 +136,30 @@
Delphi.Personality.12
- Package
+ Console
- dmvcframeworkDT.dpk
+ middleware_cors.dpr
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
-
-
+
+
+
+
+
+ middleware_cors.exe
true
-
-
-
- true
-
-
-
-
-
- true
-
-
-
-
+
1
@@ -598,6 +551,127 @@
0
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
@@ -798,127 +872,6 @@
1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
diff --git a/samples/renders/RenderSampleControllerU.pas b/samples/renders/RenderSampleControllerU.pas
index d87058fa..ac6f644d 100644
--- a/samples/renders/RenderSampleControllerU.pas
+++ b/samples/renders/RenderSampleControllerU.pas
@@ -32,7 +32,9 @@ uses
MVCFramework,
MVCFramework.Commons,
MVCFramework.Serializer.Intf,
- System.Rtti, BusinessObjectsU;
+ System.Rtti,
+ System.Generics.Collections,
+ BusinessObjectsU, Data.DB;
type
@@ -42,6 +44,18 @@ type
procedure OnBeforeAction(AContext: TWebContext; const AActionName: string;
var AHandled: Boolean); override;
public
+ // Result BASED
+ [MVCHTTPMethod([httpGET])]
+ [MVCPath('/func/people')]
+ [MVCProduces('application/json')]
+ function GetPeople_AsObjectList_AsFunction: TEnumerable;
+
+ [MVCHTTPMethod([httpGET])]
+ [MVCPath('/func/customers/simple')]
+ function GetCustomers_AsDataSet_AsFunction: TDataSet;
+
+
+ // Render BASED
[MVCHTTPMethod([httpGET])]
[MVCPath('/customers/simple')]
procedure GetCustomers_AsDataSet;
@@ -266,10 +280,9 @@ uses
InMemoryDataU,
JsonDataObjects,
MVCFramework.Serializer.JsonDataObjects,
- Data.DB,
Web.HTTPApp,
Graphics,
- System.Types;
+ System.Types, FireDAC.Comp.Client;
procedure DrawLogo(const Logo: TBitmap);
var
@@ -515,6 +528,20 @@ begin
end;
end;
+function TRenderSampleController.GetCustomers_AsDataSet_AsFunction: TDataSet;
+var
+ lDM: TMyDataModule;
+begin
+ lDM := TMyDataModule.Create(nil);
+ try
+ lDM.qryCustomers.Open;
+ Result := TFDMemTable.Create(nil);
+ TFDMemTable(Result).CloneCursor(lDM.qryCustomers, True);
+ finally
+ lDM.Free;
+ end;
+end;
+
procedure TRenderSampleController.GetCustomersAsDataSetWithRefLinks;
var
lDM: TMyDataModule;
@@ -909,6 +936,14 @@ begin
Render(HTTP_STATUS.OK, ObjectDict().Add('data', People));
end;
+function TRenderSampleController.GetPeople_AsObjectList_AsFunction: TEnumerable;
+begin
+ Result := TObjectList.Create(True);
+ TObjectList(Result).Add(TPerson.GetNew('Daniele','Teti', EncodeDate(1979, 11, 4), True));
+ TObjectList(Result).Add(TPerson.GetNew('John','Doe', EncodeDate(1879, 10, 2), False));
+ TObjectList(Result).Add(TPerson.GetNew('Jane','Doe', EncodeDate(1883, 1, 5), True));
+end;
+
procedure TRenderSampleController.GetPeople_AsObjectList_HATEOAS;
var
p: TPerson;
diff --git a/samples/renders/renders.dproj b/samples/renders/renders.dproj
index a8839b78..1ddbd51b 100644
--- a/samples/renders/renders.dproj
+++ b/samples/renders/renders.dproj
@@ -215,12 +215,12 @@
+
true
-
true
@@ -627,6 +627,127 @@
0
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
@@ -827,127 +948,6 @@
1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
diff --git a/samples/session_file_based/AppControllerU.pas b/samples/session_file_based/AppControllerU.pas
new file mode 100644
index 00000000..bdac9165
--- /dev/null
+++ b/samples/session_file_based/AppControllerU.pas
@@ -0,0 +1,102 @@
+unit AppControllerU;
+
+interface
+
+uses
+ MVCFramework,
+ MVCFramework.Commons,
+ MVCFramework.Logger;
+
+type
+ [MVCPath('/')]
+ TApp1MainController = class(TMVCController)
+ public
+ [MVCPath('/name')]
+ [MVCHTTPMethod([httpGET])]
+ procedure Index;
+
+ [MVCPath('/list')]
+ [MVCHTTPMethod([httpGET])]
+ procedure GetCustomSessionData;
+
+ [MVCPath('/login/($username)')]
+ [MVCHTTPMethod([httpGET])]
+ procedure DoLogin(username: String);
+
+ [MVCPath('/fruit/($nameOfFruit)')]
+ [MVCHTTPMethod([httpGET])]
+ procedure RegisterFruit(nameOfFruit: String);
+
+ [MVCPath('/logout')]
+ [MVCHTTPMethod([httpGET])]
+ procedure DoLogout;
+
+ end;
+
+implementation
+
+uses
+ System.SysUtils,
+ System.Classes;
+
+{ TApp1MainController }
+
+procedure TApp1MainController.DoLogin(username: String);
+begin
+ Session['username'] := username;
+ ResponseStream
+ .AppendLine('Logged as ' + username)
+ .AppendLine
+ .AppendLine('in address of browser type: ')
+ .AppendLine('http://localhost:8080/list to check the current values in session ')
+ .AppendLine('http://localhost:8080/fruit/apple to register apple ')
+ .AppendLine('http://localhost:8080/fruit/banana to register banana ')
+ .AppendLine('http://localhost:8080/logout to end session ')
+ .AppendLine('http://localhost:8080/login/johndoe to login as johndoe');
+ RenderResponseStream;
+end;
+
+procedure TApp1MainController.RegisterFruit(nameOfFruit: String);
+begin
+ Session[nameOfFruit] := nameOfFruit;
+ Redirect('/list');
+end;
+
+procedure TApp1MainController.DoLogout;
+begin
+ Context.SessionStop(false);
+ Render('Logout');
+end;
+
+procedure TApp1MainController.GetCustomSessionData;
+var
+ I: Integer;
+ lList: TArray;
+begin
+ lList := Session.Keys;
+ ResponseStream.AppendLine('List of fruits:');
+ for I := 0 to Length(lList) - 1 do
+ begin
+ ResponseStream.AppendLine(IntToStr(I + 1) + '-' + Session[lList[I]]);
+ end;
+ RenderResponseStream;
+end;
+
+procedure TApp1MainController.Index;
+begin
+ ContentType := TMVCMediaType.TEXT_PLAIN;
+
+ // do not create session if not already created
+ if Context.SessionStarted then
+ begin
+ // automaticaly create the session
+ Render('Session[''username''] = ' + Session['username']);
+ end
+ else
+ begin
+ Render(400, 'Session not created. Do login first');
+ end;
+end;
+
+end.
+
diff --git a/samples/session_file_based/FileBasedSessionSample.dpr b/samples/session_file_based/FileBasedSessionSample.dpr
new file mode 100644
index 00000000..bf342dbd
--- /dev/null
+++ b/samples/session_file_based/FileBasedSessionSample.dpr
@@ -0,0 +1,55 @@
+program FileBasedSessionSample;
+
+{$APPTYPE CONSOLE}
+
+
+uses
+ System.SysUtils,
+ MVCFramework,
+ MVCFramework.Signal,
+ {$IFDEF MSWINDOWS}
+ Winapi.Windows,
+ Winapi.ShellAPI,
+ {$ENDIF }
+ Web.WebReq,
+ Web.WebBroker,
+ IdHTTPWebBrokerBridge,
+ WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule},
+ AppControllerU in 'AppControllerU.pas';
+
+{$R *.res}
+
+
+procedure RunServer(APort: Integer);
+var
+ LServer: TIdHTTPWebBrokerBridge;
+begin
+ Writeln(Format('Starting HTTP Server or port %d', [APort]));
+ LServer := TIdHTTPWebBrokerBridge.Create(nil);
+ try
+ LServer.DefaultPort := APort;
+ LServer.Active := True;
+ {$IFDEF MSWINDOWS}
+ //ShellExecute(0, 'open', PChar('http://localhost:' + IntToStr(APort) + '/login/john'), nil, nil, SW_SHOW);
+ {$ENDIF}
+ Writeln('CTRL+C to stop the server');
+ WaitForTerminationSignal;
+ EnterInShutdownState;
+ finally
+ LServer.Free;
+ end;
+end;
+
+begin
+ ReportMemoryLeaksOnShutdown := True;
+ try
+ if WebRequestHandler <> nil then
+ WebRequestHandler.WebModuleClass := WebModuleClass;
+ WebRequestHandlerProc.MaxConnections := 1024;
+ RunServer(8080);
+ except
+ on E: Exception do
+ Writeln(E.ClassName, ': ', E.Message);
+ end
+
+end.
diff --git a/packages/d111/dmvcframeworkDT.dproj b/samples/session_file_based/FileBasedSessionSample.dproj
similarity index 77%
rename from packages/d111/dmvcframeworkDT.dproj
rename to samples/session_file_based/FileBasedSessionSample.dproj
index 4690f54f..4e9c4a3c 100644
--- a/packages/d111/dmvcframeworkDT.dproj
+++ b/samples/session_file_based/FileBasedSessionSample.dproj
@@ -1,28 +1,18 @@
- {84344511-1DC2-41BA-8689-9F36C1D475BE}
- dmvcframeworkDT.dpk
+ {F9CBCE21-869A-478F-992C-88FCAC97BC8B}
19.5
- None
+ VCL
+ FileBasedSessionSample.dpr
True
Debug
Win32
1
- Package
+ Console
true
-
- true
- Base
- true
-
-
- true
- Base
- true
-
true
Base
@@ -49,13 +39,15 @@
Base
true
-
- true
- Cfg_2
- true
- true
-
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ FileBasedSessionSample
+ ..\..\sources;..\..\lib\delphistompclient;..\..\lib\loggerpro;..\..\lib\dmustache;$(DCC_UnitSearchPath)
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ None
+ 1040
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
.\$(Platform)\$(Config)
.\$(Platform)\$(Config)
false
@@ -63,37 +55,14 @@
false
false
false
- true
- true
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- All
- dmvcframeworkDT
- 1040
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- DelphiMVCFramework IDE Expert
-
-
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
-
-
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
1033
- rtl;IndySystem;IndyProtocols;IndyCore;dbrtl;dmvcframeworkRT;$(DCC_UsePackage)
- ..\..\sources;$(DCC_UnitSearchPath)
- DelphiMVCFramework 3.x - Design Time Support
- 110
+ cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;JvDotNetCtrls;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;JvXPCtrls;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;FMXfrx17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;CloudService;dxPScxCommonRS17;FmxTeeUI;frxDB17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;JvRuntimeDesign;dxPScxVGridLnkRS17;JclDeveloperTools;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;MyFrameTestPackage;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;fs17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;DataBindingsVCL170;dxSkinOffice2010SilverRS17;vcldbx;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DataBindings;DBXOdbcDriver;IcsCommonDXE3Run;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;FMXTee;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;Jcl;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;Intraweb;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;fsDB17;inet;dorm_runtime_xe3;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;inetdbbde;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;MetropolisUILiveTile;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;vclribbon;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;CodeSiteExpressPkg;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;JvDocking;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;frx17;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;JclContainers;NxAddonsRun_dxe3;CPortLibDXE;JvSystem;dxorgcRS17;svnui;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;FMXfrxDB17;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;JclVcl;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;frxe17;svn;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;bdertl;VirtualTreesR;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
- rtl;IndySystem;IndyProtocols;IndyCore;dbrtl;$(DCC_UsePackage)
+ cxPivotGridChartRS17;JvMM;dxSkinSevenRS17;dxSkinBlueprintRS17;dxSkinHighContrastRS17;dxSkinOffice2007BlackRS17;dxCoreRS17;cxPageControldxBarPopupMenuRS17;dxSkinXmas2008BlueRS17;dxPSDBTeeChartRS17;JvCrypt;dxPSTeeChartRS17;dxSkinSummer2008RS17;dxPScxSchedulerLnkRS17;dxSkinBlueRS17;dxSkinDarkRoomRS17;DBXInterBaseDriver;DataSnapServer;DataSnapCommon;dxPScxTLLnkRS17;JvNet;dxRibbonRS17;DbxCommonDriver;cxDataRS17;vclimg;dxSkinsdxBarPainterRS17;dxPSdxDBTVLnkRS17;dbxcds;DatasnapConnectorsFreePascal;NxDBGridDsgn_dxe3;dxSkinMoneyTwinsRS17;vcldb;cxExportRS17;dxPSCoreRS17;dxBarExtItemsRS17;dxGDIPlusRS17;dxNavBarRS17;CustomIPTransport;cxLibraryRS17;cxGridRS17;dxSkinOffice2010BlackRS17;dsnap;IndyIPServer;IndyCore;dxSkinMcSkinRS17;dxPScxCommonRS17;AnyDAC_PhysDb2_D17;dxSkinsdxDLPainterRS17;dxSkiniMaginaryRS17;JvDB;dxPScxVGridLnkRS17;dxSkinSevenClassicRS17;dxPScxExtCommonRS17;dxPScxSSLnkRS17;NxGridRun_dxe3;dxSkinLilianRS17;dxPSdxLCLnkRS17;dxSkinOffice2010BlueRS17;NxCommonRun_dxe3;bindcompfmx;dxSkinOffice2010SilverRS17;cxSchedulerGridRS17;dbrtl;bindcomp;inetdb;JvPluginSystem;dxBarRS17;DBXOdbcDriver;JvCmp;dxBarDBNavRS17;dxSkinWhiteprintRS17;JvTimeFramework;xmlrtl;dxSkinsdxRibbonPainterRS17;ibxpress;dxDockingRS17;vclactnband;bindengine;soaprtl;dxADOServerModeRS17;bindcompvcl;dxBarExtDBItemsRS17;dxPSPrVwRibbonRS17;vclie;dxSkinOffice2007PinkRS17;cxPageControlRS17;dxSkinscxPCPainterRS17;AnyDAC_PhysADS_D17;AnyDAC_PhysIB_D17;dxmdsRS17;dxSkinTheAsphaltWorldRS17;DBXInformixDriver;dxPsPrVwAdvRS17;NxInspectorRun_dxe3;dxSkinSilverRS17;dxdborRS17;dsnapcon;DBXFirebirdDriver;inet;JvPascalInterpreter;vclx;dxSkinStardustRS17;cxEditorsRS17;DBXSybaseASADriver;NxInspectorDsgn_dxe3;dbexpress;IndyIPClient;AnyDAC_PhysMySQL_D17;cxTreeListdxBarPopupMenuRS17;dxSkinVS2010RS17;NxGridDsgn_dxe3;dxThemeRS17;DBXSqliteDriver;dxPScxGridLnkRS17;fmx;JvDlgs;IndySystem;TeeDB;dxSkinValentineRS17;vclib;DataSnapClient;dxSkinDevExpressStyleRS17;DataSnapProviderClient;DBXSybaseASEDriver;cxBarEditItemRS17;AnyDAC_PhysMSAcc_D17;dxServerModeRS17;cxPivotGridOLAPRS17;cxSchedulerRS17;AnyDAC_PhysSQLITE_D17;dxPSLnksRS17;dxSkinPumpkinRS17;dxPSdxDBOCLnkRS17;cxVerticalGridRS17;dxSkinSpringTimeRS17;vcldsnap;dxSkinDevExpressDarkStyleRS17;DBXDb2Driver;AnyDAC_ComI_D17;DBXOracleDriver;AnyDAC_PhysMSSQL_D17;JvCore;NxDBGridRun_dxe3;AnyDAC_Comp_D17;cxSpreadSheetRS17;dxSkinLiquidSkyRS17;AnyDAC_PhysODBC_D17;fmxase;vcl;dxSkinOffice2007SilverRS17;AnyDAC_PhysPg_D17;IndyIPCommon;DBXMSSQLDriver;dxPSdxOCLnkRS17;dcldxSkinsCoreRS17;JvAppFrm;AnyDAC_PhysASA_D17;inetdbxpress;webdsnap;NxCollectionRun_dxe3;AnyDAC_PhysOracle_D17;dxSkinCoffeeRS17;adortl;dxSkinscxSchedulerPainterRS17;JvWizards;NxCollectionDsgn_dxe3;NxCommonDsgn_dxe3;dxtrmdRS17;dxPScxPCProdRS17;AnyDAC_GUIxForms_D17;JvBands;rtl;DbxClientDriver;AnyDAC_PhysTDBX_D17;dxTabbedMDIRS17;dxComnRS17;dxSkinSharpPlusRS17;dxSkinsCoreRS17;dxSkinLondonLiquidSkyRS17;dxdbtrRS17;Tee;NxAddonsRun_dxe3;JvSystem;dxorgcRS17;dxSkinBlackRS17;JvControls;NxSheetRun_dxe3;IndyProtocols;DBXMySQLDriver;dxLayoutControlRS17;bindcompdbx;TeeUI;JvJans;JvPrintPreview;JvPageComps;JvStdCtrls;JvCustom;dxSkinOffice2007BlueRS17;dxPScxPivotGridLnkRS17;dxSpellCheckerRS17;vcltouch;dxSkinOffice2007GreenRS17;dxSkinSharpRS17;websnap;dxSkinFoggyRS17;dxTileControlRS17;VclSmp;dxSkinDarkSideRS17;cxPivotGridRS17;DataSnapConnectors;AnyDAC_Phys_D17;fmxobj;SynEdit_RXE3;cxTreeListRS17;dxPSdxFCLnkRS17;dxSkinGlassOceansRS17;dxFlowChartRS17;fmxdae;dxSkinsdxNavBarPainterRS17;DataSnapIndy10ServerTransport;dxDBXServerModeRS17;dxSkinCaramelRS17;$(DCC_UsePackage)
DEBUG;$(DCC_Define)
@@ -104,12 +73,10 @@
true
- false
- true
+ 3
+ true
1033
- false
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=Daniele Teti and the DMVCFramework Team;LegalTrademarks=DelphiMVCFramework;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 111
+ false
false
@@ -117,51 +84,15 @@
0
0
-
- true
- 1033
-
MainSource
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ TWebModule
-
-
-
-
-
-
-
-
- ICON
- DMVCNewProjectIcon
-
-
- ICON
- DMVCNewUnitIcon
-
-
- BITMAP
- SplashScreen
-
+
Base
@@ -176,37 +107,60 @@
Delphi.Personality.12
- Package
+
+
+ False
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1040
+ 1252
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+
+
+
+
+
- dmvcframeworkDT.dpk
+ FileBasedSessionSample.dpr
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
+ Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver
+ Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server
-
-
-
+
+
+ FileBasedSessionSample.exe
true
-
-
- true
-
-
-
-
-
- true
-
-
-
-
+
1
@@ -933,9 +887,6 @@
- False
- False
- False
True
False
diff --git a/samples/session_file_based/WebModuleUnit1.dfm b/samples/session_file_based/WebModuleUnit1.dfm
new file mode 100644
index 00000000..2c58d387
--- /dev/null
+++ b/samples/session_file_based/WebModuleUnit1.dfm
@@ -0,0 +1,11 @@
+object WebModule1: TWebModule1
+ OnCreate = WebModuleCreate
+ Actions = <
+ item
+ Default = True
+ Name = 'DefaultHandler'
+ PathInfo = '/'
+ end>
+ Height = 230
+ Width = 415
+end
diff --git a/samples/session_file_based/WebModuleUnit1.pas b/samples/session_file_based/WebModuleUnit1.pas
new file mode 100644
index 00000000..b7d8a556
--- /dev/null
+++ b/samples/session_file_based/WebModuleUnit1.pas
@@ -0,0 +1,44 @@
+unit WebModuleUnit1;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ Web.HTTPApp,
+ MVCFramework;
+
+type
+ TWebModule1 = class(TWebModule)
+ procedure WebModuleCreate(Sender: TObject);
+
+ private
+ MVC: TMVCEngine;
+
+ public
+ { Public declarations }
+ end;
+
+var
+ WebModuleClass: TComponentClass = TWebModule1;
+
+implementation
+
+{$R *.dfm}
+
+
+uses AppControllerU, MVCFramework.Commons;
+
+procedure TWebModule1.WebModuleCreate(Sender: TObject);
+begin
+ MVC := TMVCEngine.Create(Self,
+ procedure(Config: TMVCConfig)
+ begin
+ Config[TMVCConfigKey.SessionTimeout] := '10'; // 10minutes
+ Config[TMVCConfigKey.DefaultContentType] := 'text/plain';
+ Config[TMVCConfigKey.SessionType] := 'file';
+ end);
+ MVC.AddController(TApp1MainController);
+end;
+
+end.
diff --git a/sources/MVCFramework.ActiveRecord.pas b/sources/MVCFramework.ActiveRecord.pas
index 877b7a76..d46ed803 100644
--- a/sources/MVCFramework.ActiveRecord.pas
+++ b/sources/MVCFramework.ActiveRecord.pas
@@ -103,6 +103,18 @@ type
procedure EndUpdates;
end;
+ TSQLQueryWithName = record
+ Name: String;
+ SQLText: String;
+ BackEnd: String; //TMVCActiveRecordBackEnd
+ end;
+
+ TRQLQueryWithName = record
+ Name: String;
+ RQLText: String;
+ end;
+
+
TFieldsMap = class(TObjectDictionary)
private
fWritableFieldsCount: Integer;
@@ -133,6 +145,22 @@ type
constructor Create(const PartitionClause: String);
end;
+ MVCNamedSQLQueryAttribute = class(MVCActiveRecordCustomAttribute)
+ public
+ Name: string;
+ SQLQuery: String;
+ Backend: String; //TMVCActiveRecordBackEnd
+ constructor Create(aName: string; aSQLSelect: String); overload;
+ constructor Create(aName: string; aSQLSelect: String; aBackEnd: String); overload;
+ end;
+
+ MVCNamedRQLQueryAttribute = class(MVCActiveRecordCustomAttribute)
+ public
+ Name: string;
+ RQLQuery: String;
+ constructor Create(aName: string; aRQL: String);
+ end;
+
MVCTableFieldAttribute = class(MVCActiveRecordCustomAttribute)
public
FieldName: string;
@@ -202,6 +230,8 @@ type
fPrimaryKeyOptions: TMVCActiveRecordFieldOptions;
fPrimaryKeySequenceName: string;
fPrimaryKeyFieldType: TFieldType;
+ fNamedSQLQueries: TArray;
+ fNamedRQLQueries: TArray;
public
constructor Create;
destructor Destroy; override;
@@ -226,7 +256,6 @@ type
fBackendDriver: string;
fTableMap: TMVCTableMap;
function GetPartitionInfo: TPartitionInfo;
- function GetBackEnd: string;
function GetConnection: TFDConnection;
procedure InitTableInfo;
class function ExecQuery(
@@ -256,7 +285,7 @@ type
const Unidirectional: Boolean;
const DirectExecute: Boolean): TDataSet; overload;
procedure FillPrimaryKey(const SequenceName: string);
- function ExecNonQuery(const SQL: string; RefreshAutoGenerated: Boolean = false): int64;
+ function ExecNonQuery(const SQL: string; RefreshAutoGenerated: Boolean = false): Int64;
overload;
class function GetByPK(aActiveRecord: TMVCActiveRecord; const aValue: string; const aFieldType: TFieldType;
const RaiseExceptionIfNotFound: Boolean): TMVCActiveRecord; overload;
@@ -330,10 +359,11 @@ type
function GenerateSelectSQL: string;
function SQLGenerator: TMVCSQLGenerator;
-
- function InternalCount(const RQL: string): int64;
+ function InternalCount(const RQL: string): Int64;
function InternalSelectRQL(const RQL: string; const MaxRecordCount: Integer)
- : TMVCActiveRecordList;
+ : TMVCActiveRecordList; overload;
+ function InternalSelectRQL(const RQL: string; const MaxRecordCount: Integer;
+ const OutList: TMVCActiveRecordList): UInt32; overload;
public
constructor Create(aLazyLoadConnection: Boolean); overload;
{ cannot be virtual! }
@@ -342,6 +372,7 @@ type
procedure EnsureConnection;
procedure Assign(ActiveRecord: TMVCActiveRecord); virtual;
procedure InvalidateConnection(const ReacquireAfterInvalidate: Boolean = false);
+ function GetBackEnd: string;
///
/// Executes an Insert (pk is null) or an Update (pk is not null)
///
@@ -354,7 +385,7 @@ type
const aRaiseException: Boolean = True): Boolean;
procedure Insert;
function GetMapping: TMVCFieldsMapping;
- function LoadByPK(const id: int64): Boolean; overload; virtual;
+ function LoadByPK(const id: Int64): Boolean; overload; virtual;
function LoadByPK(const id: string): Boolean; overload; virtual;
function LoadByPK(const id: TGuid): Boolean; overload; virtual;
function LoadByPK(const id: string; const aFieldType: TFieldType): Boolean; overload; virtual;
@@ -372,51 +403,25 @@ type
procedure AddChildren(const ChildObject: TObject);
procedure RemoveChildren(const ChildObject: TObject);
function GetPrimaryKeyFieldType: TFieldType;
- // dynamic access
- property Attributes[const AttrName: string]: TValue read GetAttributes write SetAttributes;
+
+ function FindSQLQueryByName(const QueryName: String; out NamedSQLQuery: TSQLQueryWithName): Boolean;
+ function FindRQLQueryByName(const QueryName: String; out NamedRQLQuery: TRQLQueryWithName): Boolean;
+
+ property Attributes[const AttrName: string]: TValue
+ read GetAttributes
+ write SetAttributes;
+
[MVCDoNotSerialize]
- property TableName: string read GetTableName write SetTableName;
+ property TableName: string
+ read GetTableName
+ write SetTableName;
+
[MVCDoNotSerialize]
- property PrimaryKeyIsAutogenerated: Boolean read GetPrimaryKeyIsAutogenerated
+ property PrimaryKeyIsAutogenerated: Boolean
+ read GetPrimaryKeyIsAutogenerated
write SetPrimaryKeyIsAutogenerated;
- class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64;
- const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
- class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: string;
- const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
- class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: TGuid;
- const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
+
class function GetScalar(const SQL: string; const Params: array of Variant): Variant;
- class function Select(const aClass: TMVCActiveRecordClass; const SQL: string;
- const Params: array of Variant)
- : TMVCActiveRecordList; overload;
- class function Select(const aClass: TMVCActiveRecordClass; const SQL: string;
- const Params: array of Variant;
- const Connection: TFDConnection): TMVCActiveRecordList; overload;
- class function SelectRQL(const aClass: TMVCActiveRecordClass; const RQL: string;
- const MaxRecordCount: Integer)
- : TMVCActiveRecordList; overload;
- class function DeleteRQL(const aClass: TMVCActiveRecordClass; const RQL: string): int64;
- function SelectRQL(const RQL: string; const MaxRecordCount: Integer)
- : TMVCActiveRecordList; overload;
- class function Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
- const Params: array of Variant)
- : TMVCActiveRecordList; overload;
- class function Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
- const Params: array of Variant;
- const Connection: TFDConnection): TMVCActiveRecordList; overload;
- class function All(const aClass: TMVCActiveRecordClass): TObjectList;
- overload;
- class function DeleteAll(const aClass: TMVCActiveRecordClass): int64; overload;
- function Count(const RQL: string = ''): int64; overload;
- class function Count(const aClass: TMVCActiveRecordClass; const RQL: string = '')
- : int64; overload;
- class function SelectDataSet(const SQL: string; const Params: array of Variant;
- const Unidirectional: Boolean = False;
- const DirectExecute: Boolean = False): TDataSet; overload;
- class function SelectDataSet(const SQL: string; const Params: array of Variant;
- const ParamTypes: array of TFieldType;
- const Unidirectional: Boolean = False;
- const DirectExecute: Boolean = False): TDataSet; overload;
class function CurrentConnection: TFDConnection;
end;
@@ -443,21 +448,55 @@ type
end;
TMVCActiveRecordHelper = class helper for TMVCActiveRecord
+ { GetByPK }
+ class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: Int64;
+ const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
+ class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: string;
+ const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
+ class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: TGuid;
+ const RaiseExceptionIfNotFound: Boolean = True): TMVCActiveRecord; overload;
class function GetByPK(const aValue: string; const aFieldType: TFieldType;
const RaiseExceptionIfNotFound: Boolean): T; overload;
- class function GetByPK(const aValue: int64;
+ class function GetByPK(const aValue: Int64;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetByPK(const aValue: string;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetByPK(const aValue: TGuid;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
+
+ { Select }
+ ///
+ /// Returns a TObjectList from a SQL using variant params
+ ///
class function Select(const SQL: string;
const Params: array of Variant;
const Options: TMVCActiveRecordLoadOptions = []): TObjectList; overload;
+ ///
+ /// Returns a TObjectList from a SQL using typed params
+ ///
class function Select(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = [])
: TObjectList; overload;
+ ///
+ /// Fills a TObjectList from a SQL using typed params.
+ /// Returns number of the records in the list (not only the selected records, but the current .Count of the list)
+ ///
+ class function Select(const SQL: string; const Params: array of Variant;
+ const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions;
+ const OutList: TObjectList): UInt32; overload;
+
+ class function Select(const aClass: TMVCActiveRecordClass; const SQL: string;
+ const Params: array of Variant)
+ : TMVCActiveRecordList; overload;
+ class function Select(const aClass: TMVCActiveRecordClass; const SQL: string;
+ const Params: array of Variant;
+ const Connection: TFDConnection): TMVCActiveRecordList; overload;
+ class function Select(const aClass: TMVCActiveRecordClass; const SQL: string;
+ const Params: array of Variant;
+ const Connection: TFDConnection; const OutList: TMVCActiveRecordList): UInt32; overload;
+
+ { SelectOne }
class function SelectOne(const SQL: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions = [];
@@ -465,14 +504,30 @@ type
class function SelectOne(const SQL: string;
const Params: array of Variant;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
+
+
+ { SelectRQL }
+ function SelectRQL(const RQL: string; const MaxRecordCount: Integer)
+ : TMVCActiveRecordList; overload;
class function SelectRQL(const RQL: string;
const MaxRecordCount: Integer)
: TObjectList; overload;
+ class function SelectRQL(const RQL: string;
+ const MaxRecordCount: Integer; const OutList: TObjectList): UInt32; overload;
class function SelectOneByRQL(const RQL: string;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
+ class function SelectRQL(const aClass: TMVCActiveRecordClass; const RQL: string;
+ const MaxRecordCount: Integer)
+ : TMVCActiveRecordList; overload;
+ class function SelectRQL(const aClass: TMVCActiveRecordClass; const RQL: string;
+ const MaxRecordCount: Integer; const OutList: TMVCActiveRecordList): UInt32; overload;
+
+ { Misc }
class function All: TObjectList; overload;
- class function DeleteRQL(const RQL: string = ''): int64; overload;
- class function Count(const RQL: string = ''): int64; overload;
+ class function DeleteRQL(const RQL: string = ''): Int64; overload;
+ class function Count(const RQL: string = ''): Int64; overload;
+
+ { Where }
class function Where(const SQLWhere: string;
const Params: array of Variant)
: TObjectList; overload;
@@ -483,6 +538,28 @@ type
class function Where(const SQLWhere: string;
const Params: array of Variant;
const ParamTypes: array of TFieldType): TObjectList; overload;
+ class function Where(const SQLWhere: string;
+ const Params: array of Variant;
+ const ParamTypes: array of TFieldType;
+ const OutList: TObjectList): UInt32; overload;
+ class function Where(
+ const aClass: TMVCActiveRecordClass;
+ const SQLWhere: string;
+ const Params: array of Variant)
+ : TMVCActiveRecordList; overload;
+ class function Where(
+ const aClass: TMVCActiveRecordClass;
+ const SQLWhere: string;
+ const Params: array of Variant;
+ const Connection: TFDConnection): TMVCActiveRecordList; overload;
+ class function Where(
+ const aClass: TMVCActiveRecordClass;
+ const SQLWhere: string;
+ const Params: array of Variant;
+ const Connection: TFDConnection;
+ const OutList: TMVCActiveRecordList): UInt32; overload;
+
+ { GetXXXByWhere }
class function GetOneByWhere(const SQLWhere: string;
const Params: array of Variant; const RaiseExceptionIfNotFound: Boolean = True): T; overload;
class function GetOneByWhere(const SQLWhere: string;
@@ -493,8 +570,45 @@ type
class function GetFirstByWhere(const SQLWhere: string;
const Params: array of Variant; const ParamTypes: array of TFieldType;
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
+
+ { Merge }
class function Merge(CurrentList,
NewList: TObjectList; const MergeMode: TMergeMode = [mmInsert, mmUpdate, mmDelete]): IMVCMultiExecutor;
+
+ { Misc }
+ class function All(const aClass: TMVCActiveRecordClass): TObjectList;
+ overload;
+ class function DeleteAll(const aClass: TMVCActiveRecordClass): Int64; overload;
+ class function DeleteRQL(const aClass: TMVCActiveRecordClass; const RQL: string): Int64; overload;
+ function Count(const RQL: string = ''): Int64; overload;
+ class function Count(const aClass: TMVCActiveRecordClass; const RQL: string = '')
+ : int64; overload;
+
+ { SelectDataSet }
+ class function SelectDataSet(const SQL: string; const Params: array of Variant;
+ const Unidirectional: Boolean = False;
+ const DirectExecute: Boolean = False): TDataSet; overload;
+ class function SelectDataSet(const SQL: string; const Params: array of Variant;
+ const ParamTypes: array of TFieldType;
+ const Unidirectional: Boolean = False;
+ const DirectExecute: Boolean = False): TDataSet; overload;
+
+ { NamedQuery}
+ class function SelectByNamedQuery(
+ const QueryName: String;
+ const Params: array of Variant;
+ const ParamTypes: array of TFieldType;
+ const Options: TMVCActiveRecordLoadOptions = []): TObjectList;
+ class function SelectRQLByNamedQuery(
+ const QueryName: String;
+ const Params: array of const;
+ const MaxRecordCount: Integer): TObjectList;
+ class function DeleteRQLByNamedQuery(
+ const QueryName: String;
+ const Params: array of const): Int64;
+ class function CountRQLByNamedQuery(
+ const QueryName: string;
+ const Params: array of const): Int64;
end;
IMVCEntitiesRegistry = interface
@@ -1234,6 +1348,43 @@ begin
end;
end;
+function TMVCActiveRecord.FindRQLQueryByName(const QueryName: String;
+ out NamedRQLQuery: TRQLQueryWithName): Boolean;
+var
+ I: Integer;
+begin
+ for I := Low(fTableMap.fNamedRQLQueries) to High(fTableMap.fNamedRQLQueries) do
+ begin
+ if SameText(QueryName, fTableMap.fNamedRQLQueries[I].Name) then
+ begin
+ NamedRQLQuery := fTableMap.fNamedRQLQueries[I];
+ Exit(True);
+ end;
+ end;
+ Result := False;
+end;
+
+function TMVCActiveRecord.FindSQLQueryByName(const QueryName: String;
+ out NamedSQLQuery: TSQLQueryWithName): Boolean;
+var
+ I: Integer;
+ lBackEnd: String;
+begin
+ for I := Low(fTableMap.fNamedSQLQueries) to High(fTableMap.fNamedSQLQueries) do
+ begin
+ if SameText(QueryName, fTableMap.fNamedSQLQueries[I].Name) then
+ begin
+ lBackEnd := fTableMap.fNamedSQLQueries[I].BackEnd;
+ if lBackEnd.IsEmpty or (lBackEnd = GetBackEnd) then
+ begin
+ NamedSQLQuery := fTableMap.fNamedSQLQueries[I];
+ Exit(True);
+ end;
+ end;
+ end;
+ Result := False;
+end;
+
class function TMVCActiveRecord.ExecQuery(const SQL: string; const Values: array of Variant;
const Unidirectional: Boolean; const DirectExecute: Boolean): TDataSet;
begin
@@ -1248,6 +1399,8 @@ var
lPrimaryFieldTypeAsStr: string;
lTableMap: TMVCTableMap;
lPKCount: Integer;
+ lNamedSQLQueryCount: Integer;
+ lNamedRQLQueryCount: Integer;
begin
if ActiveRecordTableMapRegistry.TryGetValue(Self, fTableMap) then
begin
@@ -1269,6 +1422,8 @@ begin
lTableMap.fRTTIType := gCtx.GetType(Self.ClassInfo) as TRttiInstanceType;
lTableMap.fObjAttributes := lTableMap.fRTTIType.GetAttributes;
lPKCount := 0;
+ lNamedSQLQueryCount := Length(lTableMap.fNamedSQLQueries);
+ lNamedRQLQueryCount := Length(lTableMap.fNamedRQLQueries);
for lAttribute in lTableMap.fObjAttributes do
begin
if lAttribute is MVCTableAttribute then
@@ -1287,13 +1442,30 @@ begin
lTableMap.fPartitionClause := MVCPartitionAttribute(lAttribute).PartitionClause;
Continue;
end;
+ if lAttribute is MVCNamedSQLQueryAttribute then
+ begin
+ Inc(lNamedSQLQueryCount);
+ SetLength(lTableMap.fNamedSQLQueries, lNamedSQLQueryCount);
+ lTableMap.fNamedSQLQueries[lNamedSQLQueryCount - 1].Name := MVCNamedSQLQueryAttribute(lAttribute).Name;
+ lTableMap.fNamedSQLQueries[lNamedSQLQueryCount - 1].SQLText := MVCNamedSQLQueryAttribute(lAttribute).SQLQuery;
+ lTableMap.fNamedSQLQueries[lNamedSQLQueryCount - 1].BackEnd := MVCNamedSQLQueryAttribute(lAttribute).Backend;
+ Continue;
+ end;
+ if lAttribute is MVCNamedRQLQueryAttribute then
+ begin
+ Inc(lNamedRQLQueryCount);
+ SetLength(lTableMap.fNamedRQLQueries, lNamedRQLQueryCount);
+ lTableMap.fNamedRQLQueries[lNamedRQLQueryCount - 1].Name := MVCNamedRQLQueryAttribute(lAttribute).Name;
+ lTableMap.fNamedRQLQueries[lNamedRQLQueryCount - 1].RQLText := MVCNamedRQLQueryAttribute(lAttribute).RQLQuery;
+ Continue;
+ end;
end;
if lTableMap.fTableName = '' then
begin
if [eaCreate, eaUpdate, eaDelete] * lTableMap.fEntityAllowedActions <> [] then
begin
- raise Exception.Create('Cannot find TableNameAttribute');
+ raise Exception.Create('Cannot find TableNameAttribute on class ' + ClassName + ' - [HINT] Is this class decorated with MVCTable and its fields with MVCTableField?');
end;
end;
@@ -1353,7 +1525,7 @@ begin
lTableMap.fMap.EndUpdates;
if (lPKCount + lTableMap.fMap.WritableFieldsCount + lTableMap.fMap.ReadableFieldsCount) = 0 then
raise EMVCActiveRecord.Create(
- 'No fields nor PKs defined. [HINT] Use MVCTableField in private fields');
+ 'No fields nor PKs defined in class ' + ClassName + '. [HINT] Use MVCTableField in private fields');
lTableMap.fPartitionInfoInternal := nil;
ActiveRecordTableMapRegistry.AddTableMap(Self, lTableMap);
@@ -1419,6 +1591,16 @@ begin
Result := GetScalar(lSQL, []);
end;
+function TMVCActiveRecord.InternalSelectRQL(const RQL: string;
+ const MaxRecordCount: Integer; const OutList: TMVCActiveRecordList): UInt32;
+var
+ lSQL: string;
+begin
+ lSQL := SQLGenerator.CreateSQLWhereByRQL(RQL, GetMapping, True, false, MaxRecordCount);
+ LogD(Format('RQL [%s] => SQL [%s]', [RQL, lSQL]));
+ Result := Where(TMVCActiveRecordClass(Self.ClassType), lSQL, [], nil, OutList);
+end;
+
function TMVCActiveRecord.InternalSelectRQL(const RQL: string; const MaxRecordCount: Integer): TMVCActiveRecordList;
var
lSQL: string;
@@ -1494,19 +1676,19 @@ begin
end;
end;
-class function TMVCActiveRecord.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: string;
+class function TMVCActiveRecordHelper.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: string;
const RaiseExceptionIfNotFound: Boolean): TMVCActiveRecord;
begin
Result := GetByPK(aClass.Create, aValue, ftString, RaiseExceptionIfNotFound);
end;
-class function TMVCActiveRecord.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64;
+class function TMVCActiveRecordHelper.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64;
const RaiseExceptionIfNotFound: Boolean): TMVCActiveRecord;
begin
Result := GetByPK(aClass.Create, aValue.ToString, ftInteger, RaiseExceptionIfNotFound);
end;
-class function TMVCActiveRecord.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: TGuid;
+class function TMVCActiveRecordHelper.GetByPK(const aClass: TMVCActiveRecordClass; const aValue: TGuid;
const RaiseExceptionIfNotFound: Boolean): TMVCActiveRecord;
begin
Result := GetByPK(aClass.Create, aValue.ToString, ftGuid, RaiseExceptionIfNotFound);
@@ -1657,6 +1839,72 @@ begin
end;
end;
+class function TMVCActiveRecordHelper.SelectRQL(const RQL: string;
+ const MaxRecordCount: Integer; const OutList: TObjectList): UInt32;
+var
+ lAR: TMVCActiveRecord;
+ lSQL: string;
+begin
+ lAR := T.Create;
+ try
+ lSQL := lAR.SQLGenerator.CreateSQLWhereByRQL(RQL, lAR.GetMapping, MaxRecordCount > -1, false, MaxRecordCount).Trim;
+ lSQL := TMVCSQLGenerator.RemoveInitialWhereKeyword(lSQL);
+ Result := Where(lSQL, [], [], OutList);
+ finally
+ lAR.Free;
+ end;
+end;
+
+class function TMVCActiveRecordHelper.SelectRQLByNamedQuery(
+ const QueryName: string;
+ const Params: array of const;
+ const MaxRecordCount: Integer): TObjectList;
+var
+ lT: T;
+ lRQLQuery: TRQLQueryWithName;
+begin
+ lT := T.Create;
+ try
+ if not lT.FindRQLQueryByName(QueryName, lRQLQuery) then
+ begin
+ raise EMVCActiveRecord.CreateFmt('NamedRQLQuery not found: %s', [QueryName]);
+ end;
+ Result := SelectRQL(Format(lRQLQuery.RQLText, Params), MaxRecordCount);
+ finally
+ lT.Free;
+ end;
+end;
+
+class function TMVCActiveRecordHelper.Where(const SQLWhere: string;
+ const Params: array of Variant; const ParamTypes: array of TFieldType;
+ const OutList: TObjectList): UInt32;
+var
+ lAR: TMVCActiveRecord;
+ lFilter: string;
+begin
+ lAR := T.Create;
+ try
+ lFilter := lAR.SQLGenerator.GetDefaultSQLFilter(True);
+ if SQLWhere.Trim.IsEmpty() or SQLWhere.Trim.StartsWith('/*limit*/') or SQLWhere.Trim.StartsWith('/*sort*/') then
+ begin
+ Result := Select(lAR.GenerateSelectSQL + lFilter + SQLWhere, Params, ParamTypes, [], OutList);
+ end
+ else
+ begin
+ if lFilter.IsEmpty then
+ begin
+ Result := Select(lAR.GenerateSelectSQL + ' WHERE ' + SQLWhere, Params, ParamTypes, [], OutList);
+ end
+ else
+ begin
+ Result := Select(lAR.GenerateSelectSQL + lFilter + ' AND ' + SQLWhere, Params, ParamTypes, [], OutList);
+ end;
+ end;
+ finally
+ lAR.Free;
+ end;
+end;
+
function TMVCActiveRecord.GetPartitionInfo: TPartitionInfo;
var
lRQLCompilerClass: TRQLCompilerClass;
@@ -1733,7 +1981,7 @@ begin
[GetEnumName(TypeInfo(TMVCEntityAction), Ord(aEntityAction)), ClassName]) at ReturnAddress;
end;
-class function TMVCActiveRecord.Count(const aClass: TMVCActiveRecordClass; const RQL: string): int64;
+class function TMVCActiveRecordHelper.Count(const aClass: TMVCActiveRecordClass; const RQL: string): int64;
var
lAR: TMVCActiveRecord;
begin
@@ -1747,7 +1995,7 @@ begin
end;
end;
-function TMVCActiveRecord.Count(const RQL: string = ''): int64;
+function TMVCActiveRecordHelper.Count(const RQL: string = ''): int64;
begin
Result := InternalCount(RQL);
end;
@@ -1757,11 +2005,49 @@ begin
Result := TMVCActiveRecord.Count(TMVCActiveRecordClass(T), RQL);
end;
+class function TMVCActiveRecordHelper.CountRQLByNamedQuery(
+ const QueryName: string;
+ const Params: array of const): Int64;
+var
+ lRQLQuery: TRQLQueryWithName;
+ lT: T;
+begin
+ lT := T.Create;
+ try
+ if not lT.FindRQLQueryByName(QueryName, lRQLQuery) then
+ begin
+ raise EMVCActiveRecord.CreateFmt('NamedRQLQuery not found: %s', [QueryName]);
+ end;
+ Result := Count(Format(lRQLQuery.RQLText, Params));
+ finally
+ lT.Free;
+ end;
+end;
+
class function TMVCActiveRecordHelper.DeleteRQL(const RQL: string): int64;
begin
Result := TMVCActiveRecord.DeleteRQL(TMVCActiveRecordClass(T), RQL);
end;
+class function TMVCActiveRecordHelper.DeleteRQLByNamedQuery(
+ const QueryName: String;
+ const Params: array of const): Int64;
+var
+ lRQLQuery: TRQLQueryWithName;
+ lT: T;
+begin
+ lT := T.Create;
+ try
+ if not lT.FindRQLQueryByName(QueryName, lRQLQuery) then
+ begin
+ raise EMVCActiveRecord.CreateFmt('NamedRQLQuery not found: %s', [QueryName]);
+ end;
+ Result := DeleteRQL(Format(lRQLQuery.RQLText, Params));
+ finally
+ lT.Free;
+ end;
+end;
+
class function TMVCActiveRecord.CurrentConnection: TFDConnection;
begin
Result := ActiveRecordConnectionsRegistry.GetCurrent;
@@ -1802,7 +2088,7 @@ begin
OnAfterDelete;
end;
-class function TMVCActiveRecord.DeleteAll(const aClass: TMVCActiveRecordClass): int64;
+class function TMVCActiveRecordHelper.DeleteAll(const aClass: TMVCActiveRecordClass): int64;
var
lAR: TMVCActiveRecord;
begin
@@ -1815,7 +2101,7 @@ begin
end;
end;
-class function TMVCActiveRecord.DeleteRQL(const aClass: TMVCActiveRecordClass; const RQL: string): int64;
+class function TMVCActiveRecordHelper.DeleteRQL(const aClass: TMVCActiveRecordClass; const RQL: string): int64;
var
lAR: TMVCActiveRecord;
begin
@@ -2446,40 +2732,25 @@ begin
end;
end;
-class function TMVCActiveRecord.Select(const aClass: TMVCActiveRecordClass; const SQL: string;
+class function TMVCActiveRecordHelper.Select(const aClass: TMVCActiveRecordClass; const SQL: string;
const Params: array of Variant): TMVCActiveRecordList;
begin
Result := Select(aClass, SQL, Params, nil);
end;
-class function TMVCActiveRecord.Select(const aClass: TMVCActiveRecordClass; const SQL: string;
+class function TMVCActiveRecordHelper.Select(const aClass: TMVCActiveRecordClass; const SQL: string;
const Params: array of Variant; const Connection: TFDConnection): TMVCActiveRecordList;
-var
- lDataSet: TDataSet;
- lAR: TMVCActiveRecord;
begin
Result := TMVCActiveRecordList.Create;
try
- lDataSet := ExecQuery(SQL, Params, Connection, True, False);
- try
- while not lDataSet.Eof do
- begin
- lAR := aClass.Create;
- Result.Add(lAR);
- lAR.LoadByDataset(lDataSet);
- lDataSet.Next;
- end;
- finally
- lDataSet.Free;
- end;
+ Select(aClass, SQL, Params, Connection, Result);
except
Result.Free;
raise;
end;
-
end;
-class function TMVCActiveRecord.SelectDataSet(const SQL: string; const Params: array of Variant;
+class function TMVCActiveRecordHelper.SelectDataSet(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Unidirectional: Boolean; const DirectExecute: Boolean): TDataSet;
begin
Result := TMVCActiveRecord.ExecQuery(SQL, Params, ParamTypes, Unidirectional, DirectExecute);
@@ -2491,17 +2762,72 @@ begin
Result := Select(SQL, Params, [], Options);
end;
-class function TMVCActiveRecord.SelectDataSet(const SQL: string; const Params: array of Variant;
+class function TMVCActiveRecordHelper.SelectDataSet(const SQL: string; const Params: array of Variant;
const Unidirectional: Boolean; const DirectExecute: Boolean): TDataSet;
begin
Result := TMVCActiveRecord.ExecQuery(SQL, Params, Unidirectional, DirectExecute);
end;
-function TMVCActiveRecord.SelectRQL(const RQL: string; const MaxRecordCount: Integer): TMVCActiveRecordList;
+function TMVCActiveRecordHelper.SelectRQL(const RQL: string; const MaxRecordCount: Integer): TMVCActiveRecordList;
begin
Result := InternalSelectRQL(RQL, MaxRecordCount);
end;
+class function TMVCActiveRecordHelper.SelectRQL(const aClass: TMVCActiveRecordClass;
+ const RQL: string; const MaxRecordCount: Integer;
+ const OutList: TMVCActiveRecordList): UInt32;
+var
+ lAR: TMVCActiveRecord;
+begin
+ lAR := aClass.Create(True);
+ try
+ Result := lAR.InternalSelectRQL(RQL, MaxRecordCount, OutList);
+ finally
+ lAR.Free;
+ end;
+end;
+
+class function TMVCActiveRecordHelper.Select(const SQL: string; const Params: array of Variant;
+ const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions; const OutList: TObjectList): UInt32;
+var
+ lDataSet: TDataSet;
+ lAR: TMVCActiveRecord;
+begin
+ lDataSet := ExecQuery(SQL, Params, ParamTypes, True, False);
+ try
+ while not lDataSet.Eof do
+ begin
+ lAR := T.Create;
+ OutList.Add(lAR);
+ lAR.LoadByDataset(lDataSet, Options);
+ lDataSet.Next;
+ end;
+ Result := OutList.Count;
+ finally
+ lDataSet.Free;
+ end;
+end;
+
+class function TMVCActiveRecordHelper.SelectByNamedQuery(
+ const QueryName: String; const Params: array of Variant;
+ const ParamTypes: array of TFieldType;
+ const Options: TMVCActiveRecordLoadOptions): TObjectList;
+var
+ lT: T;
+ lSQLQuery: TSQLQueryWithName;
+begin
+ lT := T.Create;
+ try
+ if not lT.FindSQLQueryByName(QueryName, lSQLQuery) then
+ begin
+ raise EMVCActiveRecord.CreateFmt('NamedSQLQuery not found: %s', [QueryName]);
+ end;
+ Result := Select(lSQLQuery.SQLText, Params, ParamTypes, Options);
+ finally
+ lT.Free;
+ end;
+end;
+
class function TMVCActiveRecordHelper.Select(const SQL: string; const Params: array of Variant;
const ParamTypes: array of TFieldType; const Options: TMVCActiveRecordLoadOptions): TObjectList;
var
@@ -2511,18 +2837,7 @@ var
begin
Result := TObjectList.Create(True);
try
- lDataSet := ExecQuery(SQL, Params, ParamTypes, True, False);
- try
- while not lDataSet.Eof do
- begin
- lAR := T.Create;
- Result.Add(lAR);
- lAR.LoadByDataset(lDataSet, Options);
- lDataSet.Next;
- end;
- finally
- lDataSet.Free;
- end;
+ Select(SQL, Params, ParamTypes, Options, Result);
except
Result.Free;
raise;
@@ -2581,32 +2896,17 @@ end;
class function TMVCActiveRecordHelper.Where(const SQLWhere: string; const Params: array of Variant;
const ParamTypes: array of TFieldType): TObjectList;
-var
- lAR: TMVCActiveRecord;
- lFilter: string;
begin
- lAR := T.Create;
+ Result := TObjectList.Create(True);
try
- lFilter := lAR.SQLGenerator.GetDefaultSQLFilter(True);
- if SQLWhere.Trim.IsEmpty() or SQLWhere.Trim.StartsWith('/*limit*/') or SQLWhere.Trim.StartsWith('/*sort*/') then
- begin
- Result := Select(lAR.GenerateSelectSQL + lFilter + SQLWhere, Params, ParamTypes)
- end
- else
- begin
- if lFilter.IsEmpty then
- Result := Select(lAR.GenerateSelectSQL + ' WHERE ' + SQLWhere, Params, ParamTypes)
- else
- begin
- Result := Select(lAR.GenerateSelectSQL + lFilter + ' AND ' + SQLWhere, Params, ParamTypes);
- end;
- end;
- finally
- lAR.Free;
+ Where(SQLWhere, Params, ParamTypes, Result);
+ except
+ Result.Free;
+ raise;
end;
end;
-class function TMVCActiveRecord.SelectRQL(const aClass: TMVCActiveRecordClass; const RQL: string;
+class function TMVCActiveRecordHelper.SelectRQL(const aClass: TMVCActiveRecordClass; const RQL: string;
const MaxRecordCount: Integer): TMVCActiveRecordList;
var
lAR: TMVCActiveRecord;
@@ -3000,6 +3300,20 @@ begin
OnAfterInsertOrUpdate;
end;
+class function TMVCActiveRecordHelper.Where(const aClass: TMVCActiveRecordClass;
+ const SQLWhere: string; const Params: array of Variant;
+ const Connection: TFDConnection; const OutList: TMVCActiveRecordList): UInt32;
+var
+ lAR: TMVCActiveRecord;
+begin
+ lAR := aClass.Create;
+ try
+ Result := Select(aClass, lAR.GenerateSelectSQL + SQLWhere, Params, Connection, OutList);
+ finally
+ lAR.Free;
+ end;
+end;
+
procedure TMVCActiveRecord.AddChildren(const ChildObject: TObject);
begin
if fChildren = nil then
@@ -3012,7 +3326,7 @@ begin
end;
end;
-class function TMVCActiveRecord.All(const aClass: TMVCActiveRecordClass): TObjectList;
+class function TMVCActiveRecordHelper.All(const aClass: TMVCActiveRecordClass): TObjectList;
var
lAR: TMVCActiveRecord;
begin
@@ -3043,22 +3357,21 @@ begin
end;
end;
-class function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
+class function TMVCActiveRecordHelper.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
const Params: array of Variant): TMVCActiveRecordList;
begin
Result := Where(aClass, SQLWhere, Params, nil);
end;
-class function TMVCActiveRecord.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
+class function TMVCActiveRecordHelper.Where(const aClass: TMVCActiveRecordClass; const SQLWhere: string;
const Params: array of Variant; const Connection: TFDConnection): TMVCActiveRecordList;
-var
- lAR: TMVCActiveRecord;
begin
- lAR := aClass.Create;
+ Result := TMVCActiveRecordList.Create;
try
- Result := Select(aClass, lAR.GenerateSelectSQL + SQLWhere, Params, Connection);
- finally
- lAR.Free;
+ Where(aClass, SQLWhere, Params, Connection, Result);
+ except
+ Result.Free;
+ raise;
end;
end;
@@ -4063,6 +4376,53 @@ begin
inherited;
end;
+class function TMVCActiveRecordHelper.Select(const aClass: TMVCActiveRecordClass;
+ const SQL: string; const Params: array of Variant;
+ const Connection: TFDConnection; const OutList: TMVCActiveRecordList): UInt32;
+var
+ lDataSet: TDataSet;
+ lAR: TMVCActiveRecord;
+begin
+ lDataSet := ExecQuery(SQL, Params, Connection, True, False);
+ try
+ while not lDataSet.Eof do
+ begin
+ lAR := aClass.Create;
+ OutList.Add(lAR);
+ lAR.LoadByDataset(lDataSet);
+ lDataSet.Next;
+ end;
+ Result := OutList.Count;
+ finally
+ lDataSet.Free;
+ end;
+end;
+
+{ MVCNamedSQLQueryAttribute }
+
+constructor MVCNamedSQLQueryAttribute.Create(aName, aSQLSelect: String);
+begin
+ Create(aName, aSQLSelect, '');
+end;
+
+constructor MVCNamedSQLQueryAttribute.Create(aName, aSQLSelect,
+ aBackEnd: String);
+begin
+ inherited Create;
+ Name := aName;
+ SQLQuery := aSQLSelect;
+ BackEnd := aBackEnd;
+end;
+
+{ MVCNamedRQLQueryAttribute }
+
+constructor MVCNamedRQLQueryAttribute.Create(aName, aRQL: String);
+begin
+ inherited Create;
+ Name := aName;
+ RQLQuery := aRQL;
+end;
+
initialization
gConnectionsLock := TObject.Create;
diff --git a/sources/MVCFramework.DotEnv.pas b/sources/MVCFramework.DotEnv.pas
index e8882ff0..f9c19f2f 100644
--- a/sources/MVCFramework.DotEnv.pas
+++ b/sources/MVCFramework.DotEnv.pas
@@ -204,7 +204,7 @@ begin
begin
fEnvPath := TPath.Combine(fEnvPath, DotEnvDirectory);
end;
- DoLog('Path = ' + DotEnvDirectory);
+ DoLog('Path = ' + fEnvPath);
fEnvDict.Clear;
lAllProfiles := ['default'] + fProfiles.ToArray();
DoLog('Active profile/s priority = [' + String.Join(',', lAllProfiles) + ']');
diff --git a/sources/MVCFramework.FireDAC.Utils.pas b/sources/MVCFramework.FireDAC.Utils.pas
index d2136f1d..570225f6 100644
--- a/sources/MVCFramework.FireDAC.Utils.pas
+++ b/sources/MVCFramework.FireDAC.Utils.pas
@@ -29,7 +29,8 @@ unit MVCFramework.FireDAC.Utils;
interface
uses
- FireDAC.Comp.Client, FireDAC.Stan.Param, System.Rtti, JsonDataObjects;
+ FireDAC.Comp.Client, FireDAC.Stan.Param, System.Rtti, JsonDataObjects,
+ Data.DB, FireDAC.Comp.DataSet;
type
TFireDACUtils = class sealed
@@ -51,13 +52,13 @@ type
TFDCustomMemTableHelper = class helper for TFDCustomMemTable
public
procedure InitFromMetadata(const AJSONMetadata: TJSONObject);
+ class function CloneFrom(const FDDataSet: TFDDataSet): TFDMemTable; static;
end;
implementation
uses
System.Generics.Collections,
- Data.DB,
System.Classes,
MVCFramework.Serializer.Commons,
System.SysUtils;
@@ -222,6 +223,12 @@ begin
end;
end;
+class function TFDCustomMemTableHelper.CloneFrom(const FDDataSet: TFDDataSet): TFDMemTable;
+begin
+ Result := TFDMemTable.Create(nil);
+ TFDMemTable(Result).CloneCursor(FDDataSet);
+end;
+
procedure TFDCustomMemTableHelper.InitFromMetadata(const AJSONMetadata: TJSONObject);
begin
TFireDACUtils.CreateDatasetFromMetadata(Self, AJSONMetadata);
diff --git a/sources/MVCFramework.JWT.pas b/sources/MVCFramework.JWT.pas
index 376447ab..6606bcb9 100644
--- a/sources/MVCFramework.JWT.pas
+++ b/sources/MVCFramework.JWT.pas
@@ -516,7 +516,7 @@ begin
FSecretKey := SecretKey;
FRegisteredClaims := TJWTRegisteredClaims.Create;
FCustomClaims := TJWTCustomClaims.Create;
- FHMACAlgorithm := HMAC_HS512;
+ FHMACAlgorithm := HMACAlgorithm;
FLeewaySeconds := ALeewaySeconds;
FRegClaimsToChecks := [TJWTCheckableClaim.ExpirationTime, TJWTCheckableClaim.NotBefore, TJWTCheckableClaim.IssuedAt];
end;
diff --git a/sources/MVCFramework.Logger.pas b/sources/MVCFramework.Logger.pas
index c3ef8813..a5355c19 100644
--- a/sources/MVCFramework.Logger.pas
+++ b/sources/MVCFramework.Logger.pas
@@ -194,14 +194,6 @@ begin
LogE(E.ClassName + ': ' + AMessage);
end;
-// procedure LogException(
-// const AException: Exception;
-// const AMessage: string);
-// begin
-// Log.Error(Format('[%s] %s (Custom message: "%s")', [AException.ClassName,
-// AException.Message, AMessage]), LOGGERPRO_TAG);
-// end;
-
procedure LogEnterMethod(const AMethodName: string);
begin
LogI('>> ' + AMethodName);
@@ -266,27 +258,27 @@ end;
procedure SetDefaultLogger(const aLogWriter: ILogWriter);
begin
- if gDefaultLogger = nil then
- begin
- TMonitor.Enter(gLock); // double check here
- try
- if gDefaultLogger = nil then
+ if gDefaultLogger = nil then
+ begin
+ TMonitor.Enter(gLock); // double check here
+ try
+ if gDefaultLogger = nil then
+ begin
+ if aLogWriter <> nil then
begin
- if aLogWriter <> nil then
- begin
- gDefaultLogger := aLogWriter;
- Log.Info('Custom Logger initialized', LOGGERPRO_TAG);
- end
- else
- begin
- InitializeDefaultLogger;
- Log.Info('Default Logger initialized', LOGGERPRO_TAG);
- end;
+ gDefaultLogger := aLogWriter;
+ Log.Info('Custom Logger initialized', LOGGERPRO_TAG);
+ end
+ else
+ begin
+ InitializeDefaultLogger;
+ Log.Info('Default Logger initialized', LOGGERPRO_TAG);
end;
- finally
- TMonitor.Exit(gLock);
end;
+ finally
+ TMonitor.Exit(gLock);
end;
+ end;
end;
procedure InitializeDefaultLogger;
diff --git a/sources/MVCFramework.RESTClient.Commons.pas b/sources/MVCFramework.RESTClient.Commons.pas
index c6fa5bb1..747970e5 100644
--- a/sources/MVCFramework.RESTClient.Commons.pas
+++ b/sources/MVCFramework.RESTClient.Commons.pas
@@ -179,6 +179,9 @@ var
begin
lDecompressed := TMemoryStream.Create;
try
+{$IF defined(MACOS) or defined(IOS)}
+ lDecompressed.CopyFrom(aContentStream, 0); // MACOS automatically decompresses response body
+{$ELSE}
if SameText(aContentEncoding, 'gzip') or SameText(aContentEncoding, 'deflate') then
begin
/// Certain types of deflate compression cannot be decompressed by the standard Zlib,
@@ -202,6 +205,7 @@ begin
begin
raise EMVCRESTClientException.CreateFmt('Content-Encoding not supported [%s]', [aContentEncoding]);
end;
+{$ENDIF}
SetLength(Result, lDecompressed.Size);
lDecompressed.Position := 0;
diff --git a/sources/MVCFramework.Router.pas b/sources/MVCFramework.Router.pas
index 8974f51c..01d0fb79 100644
--- a/sources/MVCFramework.Router.pas
+++ b/sources/MVCFramework.Router.pas
@@ -250,7 +250,7 @@ begin
begin
if LMethod.Visibility <> mvPublic then // 2020-08-08
Continue;
- if (LMethod.MethodKind <> mkProcedure) { or LMethod.IsClassMethod } then
+ if not (LMethod.MethodKind in [mkProcedure, mkFunction]) then
Continue;
LAttributes := LMethod.GetAttributes;
diff --git a/sources/MVCFramework.Serializer.Commons.pas b/sources/MVCFramework.Serializer.Commons.pas
index 4dd392f0..d1095fe3 100644
--- a/sources/MVCFramework.Serializer.Commons.pas
+++ b/sources/MVCFramework.Serializer.Commons.pas
@@ -1141,7 +1141,7 @@ begin
begin
// sqlite doesn't support boolean, so are identified as integers
// so we need to do some more checks...
- if (aRTTIField.FieldType.TypeKind = tkEnumeration) and (aRTTIField.Name.ToLower.Contains('bool')) then
+ if (aRTTIField.FieldType.TypeKind = tkEnumeration) and (aRTTIField.FieldType.Handle = TypeInfo(Boolean)) then
begin
aRTTIField.SetValue(AObject, AField.AsInteger = 1);
end
diff --git a/sources/MVCFramework.Serializer.HTML.pas b/sources/MVCFramework.Serializer.HTML.pas
index 4b8eb36e..3492bba5 100644
--- a/sources/MVCFramework.Serializer.HTML.pas
+++ b/sources/MVCFramework.Serializer.HTML.pas
@@ -77,7 +77,6 @@ type
const ASerializationAction: TMVCSerializationAction = nil
): string; overload;
-
function SerializeCollection(
const AList: TObject;
const AType: TMVCSerializationType = stDefault;
@@ -151,6 +150,12 @@ type
const AIgnoredFields: TMVCIgnoredList = [];
const ANameCase: TMVCNameCase = ncAsIs
);
+
+ function SerializeArrayOfRecord(
+ var ATValueContainingAnArray: TValue;
+ const AType: TMVCSerializationType = stDefault;
+ const AIgnoredAttributes: TMVCIgnoredList = nil;
+ const ASerializationAction: TMVCSerializationAction = nil): string;
end;
implementation
@@ -274,6 +279,14 @@ begin
RaiseNotImplemented;
end;
+function TMVCHTMLSerializer.SerializeArrayOfRecord(
+ var ATValueContainingAnArray: TValue; const AType: TMVCSerializationType;
+ const AIgnoredAttributes: TMVCIgnoredList;
+ const ASerializationAction: TMVCSerializationAction): string;
+begin
+ RaiseNotImplemented;
+end;
+
function TMVCHTMLSerializer.SerializeCollection(const AList: IInterface;
const AType: TMVCSerializationType; const AIgnoredAttributes: TMVCIgnoredList;
const ASerializationAction: TMVCSerializationAction): string;
diff --git a/sources/MVCFramework.Serializer.Intf.pas b/sources/MVCFramework.Serializer.Intf.pas
index 0a07a79f..b4bd50d5 100644
--- a/sources/MVCFramework.Serializer.Intf.pas
+++ b/sources/MVCFramework.Serializer.Intf.pas
@@ -94,6 +94,13 @@ type
const ASerializationAction: TMVCSerializationAction = nil
): string; overload;
+ function SerializeArrayOfRecord(
+ var ATValueContainingAnArray: TValue;
+ const AType: TMVCSerializationType = stDefault;
+ const AIgnoredAttributes: TMVCIgnoredList = nil;
+ const ASerializationAction: TMVCSerializationAction = nil
+ ): string; overload;
+
function SerializeCollection(
const AList: TObject;
const AType: TMVCSerializationType = stDefault;
diff --git a/sources/MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas b/sources/MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas
index 1b7a97d8..f55fab67 100644
--- a/sources/MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas
+++ b/sources/MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas
@@ -72,6 +72,11 @@ type
end;
TMVCObjectDictionarySerializer = class(TInterfacedObject, IMVCTypeSerializer)
+ private
+ procedure InternalSerializeIMVCObjectDictionary(
+ lObjDict: TMVCObjectDictionary;
+ var lOutObject: TJsonObject;
+ const ASerializationAction: TMVCSerializationAction);
protected
fCurrentSerializer: TMVCJsonDataObjectsSerializer;
public
@@ -469,27 +474,28 @@ procedure TMVCObjectDictionarySerializer.SerializeAttribute(
const AElementValue: TValue; const APropertyName: string;
const ASerializerObject: TObject;
const AAttributes: TArray);
-begin
- raise EMVCDeserializationException.Create('Serialization as attribute not supported for this type');
-end;
-
-procedure TMVCObjectDictionarySerializer.SerializeRoot(const AObject: TObject;
- out ASerializerObject: TObject; const AAttributes: TArray;
- const ASerializationAction: TMVCSerializationAction);
var
lObjDict: TMVCObjectDictionary;
- lOutObject, lOutCustom: TJsonObject;
+ lOutObject: TJsonObject;
+begin
+ lObjDict := TMVCObjectDictionary(AElementValue.AsInterface);
+ lOutObject := TJsonObject(ASerializerObject);
+ InternalSerializeIMVCObjectDictionary(lObjDict, lOutObject, nil);
+end;
+
+procedure TMVCObjectDictionarySerializer.InternalSerializeIMVCObjectDictionary(
+ lObjDict: TMVCObjectDictionary;
+ var lOutObject: TJsonObject;
+ const ASerializationAction: TMVCSerializationAction);
+var
+ lOutCustom: TJsonObject;
lName: string;
lObj: TMVCObjectDictionary.TMVCObjectDictionaryValueItem;
lList: IMVCList;
lLinks: IMVCLinks;
lJSONType: TJsonDataType;
lJSONValue: TJsonBaseObject;
-
begin
- lObjDict := TMVCObjectDictionary(AObject);
- lOutObject := TJsonObject.Create;
- try
for lName in lObjDict.Keys do
begin
lObj := lObjDict.Items[lName];
@@ -585,10 +591,22 @@ begin
RaiseSerializationError('Invalid JSON');
end;
end;
- // fCurrentSerializer.InternalObjectToJsonObject(lObj.Data, lOutObject.O[lName],
- // TMVCSerializationType.stDefault, [], lObj.SerializationAction, lLinks, nil);
end;
end
+
+end;
+
+procedure TMVCObjectDictionarySerializer.SerializeRoot(const AObject: TObject;
+ out ASerializerObject: TObject; const AAttributes: TArray;
+ const ASerializationAction: TMVCSerializationAction);
+var
+ lObjDict: TMVCObjectDictionary;
+ lOutObject: TJsonObject;
+begin
+ lObjDict := TMVCObjectDictionary(AObject);
+ lOutObject := TJsonObject.Create;
+ try
+ InternalSerializeIMVCObjectDictionary(lObjDict, lOutObject, ASerializationAction);
except
lOutObject.Free;
raise;
diff --git a/sources/MVCFramework.Serializer.JsonDataObjects.pas b/sources/MVCFramework.Serializer.JsonDataObjects.pas
index 792dec80..6c6ec09c 100644
--- a/sources/MVCFramework.Serializer.JsonDataObjects.pas
+++ b/sources/MVCFramework.Serializer.JsonDataObjects.pas
@@ -174,6 +174,13 @@ type
const AType: TMVCSerializationType = stDefault; const AIgnoredAttributes: TMVCIgnoredList = nil;
const ASerializationAction: TMVCSerializationAction = nil): string; overload;
+ function SerializeArrayOfRecord(
+ var ATValueContainingAnArray: TValue;
+ const AType: TMVCSerializationType = stDefault;
+ const AIgnoredAttributes: TMVCIgnoredList = nil;
+ const ASerializationAction: TMVCSerializationAction = nil
+ ): string; overload;
+
procedure RecordToJsonObject(const ARecord: Pointer; const ARecordTypeInfo: PTypeInfo;
const AJSONObject: TJDOJsonObject; const AType: TMVCSerializationType; const AIgnoredAttributes: TMVCIgnoredList);
@@ -3027,7 +3034,14 @@ begin
begin
if Obj <> nil then
begin
- ObjectToJsonObject(Obj, JSONArray.AddObject, GetSerializationType(Obj, AType), AIgnoredAttributes)
+ if Obj is TDataSet then
+ begin
+ DataSetToJsonArray(TDataSet(Obj), JSONArray.AddArray, TMVCNameCase.ncLowerCase, nil,nil,);
+ end
+ else
+ begin
+ ObjectToJsonObject(Obj, JSONArray.AddObject, GetSerializationType(Obj, AType), AIgnoredAttributes)
+ end;
end
else
begin
@@ -3042,6 +3056,55 @@ begin
end;
end;
+function TMVCJsonDataObjectsSerializer.SerializeArrayOfRecord(
+ var ATValueContainingAnArray: TValue; const AType: TMVCSerializationType;
+ const AIgnoredAttributes: TMVCIgnoredList;
+ const ASerializationAction: TMVCSerializationAction): string;
+var
+ I: Integer;
+ lCurrentArrayItem: TValue;
+ lJSONArr: TJsonArray;
+ lJObj: TJsonObject;
+begin
+ if not ATValueContainingAnArray.IsArray then
+ begin
+ raise EMVCSerializationException.Create(String(ATValueContainingAnArray.TypeInfo^.Name) + ' is not an array');
+ end;
+ if ATValueContainingAnArray.GetArrayLength = 0 then
+ begin
+ Result := '[]';
+ end;
+
+ lJSONArr := TJsonArray.Create;
+ try
+ for I := 0 to ATValueContainingAnArray.GetArrayLength - 1 do
+ begin
+ lJObj := lJSONArr.AddObject;
+ lCurrentArrayItem := ATValueContainingAnArray.GetArrayElement(I);
+ if lCurrentArrayItem.IsObjectInstance then
+ begin
+ raise EMVCSerializationException.CreateFmt('Found a "%s" while serializing array. Instance types not allowed in arrays - [HINT] Use list of objects instead of array', [lCurrentArrayItem.AsObject.ClassName]);
+ end
+ else
+ begin
+ InternalRecordToJsonObject(
+ lCurrentArrayItem.GetReferenceToRawData,
+ lCurrentArrayItem.TypeInfo,
+ lJObj,
+ TMVCSerializationType.stFields,
+ nil,
+ nil,
+ nil,
+ nil
+ );
+ end;
+ end;
+ Result := lJSONArr.ToJSON();
+ finally
+ lJSONArr.free;
+ end;
+end;
+
function TMVCJsonDataObjectsSerializer.SerializeCollection(const AList: IInterface; const AType: TMVCSerializationType;
const AIgnoredAttributes: TMVCIgnoredList; const ASerializationAction: TMVCSerializationAction): string;
begin
@@ -3731,7 +3794,6 @@ begin
raise;
end;
end;
- // lSer.JsonArrayToList(AJsonArray, AList, AClazz, AType, AIgnoredAttributes);
finally
lSer.Free;
end;
diff --git a/sources/MVCFramework.Session.pas b/sources/MVCFramework.Session.pas
index 18cbc8f7..075afca7 100644
--- a/sources/MVCFramework.Session.pas
+++ b/sources/MVCFramework.Session.pas
@@ -32,15 +32,18 @@ uses
System.SyncObjs,
System.SysUtils,
System.DateUtils,
- System.Generics.Collections;
+ System.Generics.Collections, MVCFramework.Commons;
const
-
DEFAULT_SESSION_INACTIVITY = 60; // in minutes
type
+ EMVCSession = class(EMVCException)
- TWebSession = class abstract
+ end;
+
+
+ TMVCWebSession = class abstract
private
FSessionId: string;
FLastAccess: TDateTime;
@@ -48,22 +51,25 @@ type
protected
function GetItems(const AKey: string): string; virtual; abstract;
procedure SetItems(const AKey, AValue: string); virtual; abstract;
+ procedure SetLastAccess(Value: TDateTime);
public
constructor Create(const ASessionId: string; const ATimeout: UInt64); virtual;
destructor Destroy; override;
procedure MarkAsUsed; virtual;
function ToString: string; override;
function IsExpired: Boolean; virtual;
-
+ function Keys: TArray; virtual; abstract;
+ class function TryFindSessionID(const ASessionID: String): Boolean; virtual;
+ class procedure TryDeleteSessionID(const ASessionID: String); virtual;
property Items[const AKey: string]: string read GetItems write SetItems; default;
property SessionId: string read FSessionId;
property LastAccess: TDateTime read FLastAccess;
property Timeout: UInt64 read FTimeout;
end;
- TWebSessionClass = class of TWebSession;
+ TMVCWebSessionClass = class of TMVCWebSession;
- TWebSessionMemory = class(TWebSession)
+ TMVCWebSessionMemory = class(TMVCWebSession)
private
FData: TDictionary;
protected
@@ -72,37 +78,61 @@ type
public
constructor Create(const ASessionId: string; const ATimeout: UInt64); override;
destructor Destroy; override;
-
function ToString: string; override;
-
property Data: TDictionary read FData;
end;
+
+ TMVCWebSessionFile = class(TMVCWebSessionMemory)
+ private
+ fSessionFolder: String;
+ protected
+ procedure StartLoading;
+ procedure EndLoading;
+ function GetFileName: String; overload;
+ class function GetFileName(const SessionFolder, SessionID: String): String; overload;
+ procedure LoadFromFile;
+ procedure SaveToFile;
+ procedure OnValueNotify(Sender: TObject; const Item: String; Action: TCollectionNotification);
+ public
+ constructor Create(const SessionID: string; const Timeout: UInt64); override;
+ destructor Destroy; override;
+ function Keys: System.TArray; override;
+ class function TryFindSessionID(const ASessionID: String): Boolean; override;
+ class procedure TryDeleteSessionID(const ASessionID: String); override;
+ end;
+
TMVCSessionFactory = class sealed
private
- FRegisteredSessionTypes: TDictionary;
+ FRegisteredSessionTypes: TDictionary;
protected
class var cInstance: TMVCSessionFactory;
constructor Create;
public
destructor Destroy; override;
- procedure RegisterSessionType(const AName: string; AWebSessionClass: TWebSessionClass);
- function CreateNewByType(const AName, ASessionId: string; const ATimeout: UInt64): TWebSession;
-
+ procedure RegisterSessionType(const AName: string; AWebSessionClass: TMVCWebSessionClass);
+ function CreateNewByType(const AName, ASessionId: string; const ATimeout: UInt64): TMVCWebSession;
+ function TryFindSessionID(const AName: string; const ASessionID: String): Boolean;
+ procedure TryDeleteSessionID(const AName: string; const ASessionID: String);
class function GetInstance: TMVCSessionFactory; static;
// class procedure DestroyInstance; static;
end;
-function GlobalSessionList: TObjectDictionary;
+function GlobalSessionList: TObjectDictionary;
implementation
+uses
+ System.IOUtils,
+ System.Classes,
+ MVCFramework.Serializer.Commons;
+
var
- GlSessionList: TObjectDictionary = nil;
+ GlSessionList: TObjectDictionary = nil;
GlLastSessionListClear: TDateTime;
GlCriticalSection: TCriticalSection;
-function GlobalSessionList: TObjectDictionary;
+function GlobalSessionList: TObjectDictionary;
var
S: string;
begin
@@ -111,7 +141,9 @@ begin
GlCriticalSection.Enter;
try
if not Assigned(GlSessionList) then
- GlSessionList := TObjectDictionary.Create([doOwnsValues]);
+ begin
+ GlSessionList := TObjectDictionary.Create([doOwnsValues]);
+ end;
finally
GlCriticalSection.Leave;
end;
@@ -122,7 +154,7 @@ begin
TMonitor.Enter(GlSessionList);
try
for S in GlSessionList.Keys do
- if TWebSession(GlSessionList.Items[S]).IsExpired then
+ if TMVCWebSession(GlSessionList.Items[S]).IsExpired then
GlSessionList.Remove(S);
GlLastSessionListClear := Now;
finally
@@ -135,19 +167,19 @@ end;
{ TWebSession }
-constructor TWebSession.Create(const ASessionId: string; const ATimeout: UInt64);
+constructor TMVCWebSession.Create(const ASessionId: string; const ATimeout: UInt64);
begin
inherited Create;
FSessionId := ASessionId;
FTimeout := ATimeout;
end;
-destructor TWebSession.Destroy;
+destructor TMVCWebSession.Destroy;
begin
inherited Destroy;
end;
-function TWebSession.IsExpired: Boolean;
+function TMVCWebSession.IsExpired: Boolean;
begin
if (FTimeout = 0) then
Result := MinutesBetween(Now, LastAccess) > DEFAULT_SESSION_INACTIVITY
@@ -155,31 +187,46 @@ begin
Result := MinutesBetween(Now, LastAccess) > FTimeout;
end;
-procedure TWebSession.MarkAsUsed;
+procedure TMVCWebSession.MarkAsUsed;
begin
FLastAccess := Now;
end;
-function TWebSession.ToString: string;
+procedure TMVCWebSession.SetLastAccess(Value: TDateTime);
+begin
+ FLastAccess := Value;
+end;
+
+function TMVCWebSession.ToString: string;
begin
Result := '';
end;
+class procedure TMVCWebSession.TryDeleteSessionID(const ASessionID: String);
+begin
+ //do nothing
+end;
+
+class function TMVCWebSession.TryFindSessionID(const ASessionID: String): Boolean;
+begin
+ Result := False;
+end;
+
{ TWebSessionMemory }
-constructor TWebSessionMemory.Create(const ASessionId: string; const ATimeout: UInt64);
+constructor TMVCWebSessionMemory.Create(const ASessionId: string; const ATimeout: UInt64);
begin
inherited Create(ASessionId, ATimeout);
FData := TDictionary.Create;
end;
-destructor TWebSessionMemory.Destroy;
+destructor TMVCWebSessionMemory.Destroy;
begin
FData.Free;
inherited Destroy;
end;
-function TWebSessionMemory.GetItems(const AKey: string): string;
+function TMVCWebSessionMemory.GetItems(const AKey: string): string;
begin
TMonitor.Enter(Self);
try
@@ -190,7 +237,7 @@ begin
end;
end;
-procedure TWebSessionMemory.SetItems(const AKey, AValue: string);
+procedure TMVCWebSessionMemory.SetItems(const AKey, AValue: string);
begin
TMonitor.Enter(Self);
try
@@ -200,7 +247,7 @@ begin
end;
end;
-function TWebSessionMemory.ToString: string;
+function TMVCWebSessionMemory.ToString: string;
var
LKey: string;
begin
@@ -214,15 +261,15 @@ end;
constructor TMVCSessionFactory.Create;
begin
inherited Create;
- FRegisteredSessionTypes := TDictionary.Create;
+ FRegisteredSessionTypes := TDictionary.Create;
end;
-function TMVCSessionFactory.CreateNewByType(const AName, ASessionId: string; const ATimeout: UInt64): TWebSession;
+function TMVCSessionFactory.CreateNewByType(const AName, ASessionId: string; const ATimeout: UInt64): TMVCWebSession;
var
- Clazz: TWebSessionClass;
+ Clazz: TMVCWebSessionClass;
begin
if not FRegisteredSessionTypes.TryGetValue(AName, Clazz) then
- raise Exception.Create('Unknown application session type');
+ raise EMVCSession.Create('Unknown application session type: ' + AName);
Result := Clazz.Create(ASessionId, ATimeout);
end;
@@ -241,14 +288,164 @@ begin
Result := cInstance;
end;
-procedure TMVCSessionFactory.RegisterSessionType(const AName: string; AWebSessionClass: TWebSessionClass);
+procedure TMVCSessionFactory.RegisterSessionType(const AName: string; AWebSessionClass: TMVCWebSessionClass);
begin
FRegisteredSessionTypes.AddOrSetValue(AName, AWebSessionClass);
end;
+procedure TMVCSessionFactory.TryDeleteSessionID(const AName, ASessionID: String);
+var
+ Clazz: TMVCWebSessionClass;
+begin
+ if not FRegisteredSessionTypes.TryGetValue(AName, Clazz) then
+ raise EMVCSession.Create('Unknown application session type: ' + AName);
+ Clazz.TryDeleteSessionID(ASessionID);
+end;
+
+function TMVCSessionFactory.TryFindSessionID(const AName: string; const ASessionID: String): Boolean;
+var
+ Clazz: TMVCWebSessionClass;
+begin
+ if not FRegisteredSessionTypes.TryGetValue(AName, Clazz) then
+ raise EMVCSession.Create('Unknown application session type: ' + AName);
+ Result := Clazz.TryFindSessionID(ASessionID);
+end;
+
+{ TWebSessionMemoryController }
+
+constructor TMVCWebSessionFile.Create(const SessionID: string; const Timeout: UInt64);
+begin
+ inherited Create(SessionID, Timeout);
+ Data.OnValueNotify := OnValueNotify;
+ fSessionFolder := TPath.Combine(AppPath, 'sessions');
+ TDirectory.CreateDirectory(fSessionFolder);
+ LoadFromFile;
+ MarkAsUsed;
+ SaveToFile;
+end;
+
+destructor TMVCWebSessionFile.Destroy;
+begin
+ inherited;
+end;
+
+procedure TMVCWebSessionFile.EndLoading;
+begin
+ Data.OnValueNotify := OnValueNotify;
+end;
+
+class function TMVCWebSessionFile.GetFileName(const SessionFolder,
+ SessionID: String): String;
+begin
+ Result := TPath.Combine(SessionFolder, SessionId);
+end;
+
+function TMVCWebSessionFile.GetFileName: String;
+begin
+ Result := GetFileName(fSessionFolder, SessionId);
+end;
+
+function TMVCWebSessionFile.Keys: System.TArray;
+begin
+ Result := Data.Keys.ToArray;
+end;
+
+procedure TMVCWebSessionFile.LoadFromFile;
+var
+ lFileName: String;
+ lFile: TStreamReader;
+ lLine: string;
+ lPieces: TArray;
+begin
+ lFileName := GetFileName;
+ if not TFile.Exists(lFileName) then
+ begin
+ Exit;
+ end;
+ //Log.Info('Loading session %s from %s', [SessionId, lFileName], 'file_session_events');
+ lFile := TFile.OpenText(lFileName);
+ try
+ StartLoading;
+ try
+ SetLastAccess(ISOTimeStampToDateTime(lFile.ReadLine));
+ while not lFile.EndOfStream do
+ begin
+ lLine := lFile.ReadLine;
+ lPieces := lLine.Split(['=']);
+ Data.Add(lPieces[0], lPieces[1]);
+ end;
+ finally
+ EndLoading;
+ end;
+ finally
+ lFile.Free;
+ end;
+end;
+
+procedure TMVCWebSessionFile.OnValueNotify(Sender: TObject; const Item: String;
+ Action: TCollectionNotification);
+begin
+ if Action in [cnAdded, cnExtracted, cnRemoved] then
+ begin
+ //Log.Info('Saving session %s because item changed [%s]', [SessionId, Item], 'file_session_events');
+ SaveToFile;
+ end;
+end;
+
+procedure TMVCWebSessionFile.SaveToFile;
+var
+ lFileName: String;
+ lPair: TPair;
+ lFile: TStreamWriter;
+begin
+ MarkAsUsed;
+ lFileName := GetFileName;
+ lFile := TFile.CreateText(lFileName);
+ try
+ lFile.WriteLine(DateTimeToISOTimeStamp(LastAccess));
+ for lPair in Data do
+ begin
+ lFile.WriteLine(String.Join('=', [lPair.Key, lPair.Value]));
+ end;
+ lFile.Close;
+ finally
+ lFile.Free;
+ end;
+end;
+
+procedure TMVCWebSessionFile.StartLoading;
+begin
+ Data.OnValueNotify := nil;
+end;
+
+class procedure TMVCWebSessionFile.TryDeleteSessionID(const ASessionID: String);
+var
+ lSessionFolder: string;
+begin
+ inherited;
+ lSessionFolder := TPath.Combine(AppPath, 'sessions');
+ if TFile.Exists(GetFileName(lSessionFolder, ASessionID)) then
+ begin
+ TFile.Delete(GetFileName(lSessionFolder, ASessionID));
+ end;
+end;
+
+class function TMVCWebSessionFile.TryFindSessionID(
+ const ASessionID: String): Boolean;
+var
+ lSessionFolder: string;
+begin
+ inherited;
+ lSessionFolder := TPath.Combine(AppPath, 'sessions');
+ Result := TFile.Exists(GetFileName(lSessionFolder, ASessionID));
+end;
+
+
initialization
-TMVCSessionFactory.GetInstance.RegisterSessionType('memory', TWebSessionMemory);
+TMVCSessionFactory.GetInstance.RegisterSessionType('memory', TMVCWebSessionMemory);
+TMVCSessionFactory.GetInstance.RegisterSessionType('file', TMVCWebSessionFile);
+
GlCriticalSection := TCriticalSection.Create;
finalization
diff --git a/sources/MVCFramework.pas b/sources/MVCFramework.pas
index 439997ac..5083835a 100644
--- a/sources/MVCFramework.pas
+++ b/sources/MVCFramework.pas
@@ -506,8 +506,8 @@ type
function IsValid: Boolean;
procedure Clear;
- procedure SaveToSession(const AWebSession: TWebSession);
- function LoadFromSession(const AWebSession: TWebSession): Boolean;
+ procedure SaveToSession(const AWebSession: TMVCWebSession);
+ function LoadFromSession(const AWebSession: TMVCWebSession): Boolean;
property UserName: string read FUserName write FUserName;
property Roles: TList read FRoles;
@@ -525,10 +525,10 @@ type
FIsSessionStarted: Boolean;
FSessionMustBeClose: Boolean;
FLoggedUser: TUser;
- FWebSession: TWebSession;
+ FWebSession: TMVCWebSession;
FData: TMVCStringDictionary;
- FIntfObject: IInterface;
- function GetWebSession: TWebSession;
+ fIntfObject: IInterface;
+ function GetWebSession: TMVCWebSession;
function GetLoggedUser: TUser;
function GetParamsTable: TMVCRequestParamsTable;
procedure SetParamsTable(const AValue: TMVCRequestParamsTable);
@@ -541,14 +541,14 @@ type
procedure BindToSession(const ASessionId: string);
function SendSessionCookie(const AContext: TWebContext): string;
function AddSessionToTheSessionList(const ASessionType, ASessionId: string;
- const ASessionTimeout: Integer): TWebSession;
+ const ASessionTimeout: Integer): TMVCWebSession;
function GetData: TMVCStringDictionary;
public
constructor Create(const ARequest: TWebRequest; const AResponse: TWebResponse;
const AConfig: TMVCConfig; const ASerializers: TDictionary);
destructor Destroy; override;
- procedure SessionStart; virtual;
+ procedure SessionStart(const SessionType: String); virtual;
procedure SessionStop(const ARaiseExceptionIfExpired: Boolean = True); virtual;
function SessionStarted: Boolean;
@@ -560,7 +560,7 @@ type
property LoggedUser: TUser read GetLoggedUser;
property Request: TMVCWebRequest read FRequest;
property Response: TMVCWebResponse read FResponse;
- property Session: TWebSession read GetWebSession;
+ property Session: TMVCWebSession read GetWebSession;
property Config: TMVCConfig read FConfig;
property Data: TMVCStringDictionary read GetData;
property CustomIntfObject: IInterface read GetIntfObject write SetIntfObject;
@@ -772,7 +772,7 @@ type
private
FViewModel: TMVCViewDataObject;
FViewDataSets: TMVCViewDataSet;
- function GetSession: TWebSession;
+ function GetSession: TMVCWebSession;
function GetViewData(const aModelName: string): TObject;
function GetViewDataset(const aDataSetName: string): TDataSet;
procedure SetViewData(const aModelName: string; const Value: TObject);
@@ -808,7 +808,7 @@ type
///
procedure LoadViewFragment(const AViewFragment: string);
- function SessionAs: T;
+ function SessionAs: T;
procedure RaiseSessionExpired; virtual;
// Avoiding mid-air collisions - support
@@ -819,7 +819,7 @@ type
// Properties
property Context: TWebContext read GetContext write FContext;
- property Session: TWebSession read GetSession;
+ property Session: TMVCWebSession read GetSession;
property ContentType: string read GetContentType write SetContentType;
property StatusCode: Integer read GetStatusCode write SetStatusCode;
procedure PushObjectToView(const aModelName: string; const AModel: TObject);
@@ -1089,7 +1089,7 @@ type
function CustomExceptionHandling(const Ex: Exception; const AController: TMVCController;
const AContext: TWebContext): Boolean;
class function GetCurrentSession(const ASessionId: string;
- const ARaiseExceptionIfExpired: Boolean = True): TWebSession; static;
+ const ARaiseExceptionIfExpired: Boolean = True): TMVCWebSession; static;
class function ExtractSessionIdFromWebRequest(const AWebRequest: TWebRequest): string; static;
class function SendSessionCookie(const AContext: TWebContext): string; overload; static;
class function SendSessionCookie(const AContext: TWebContext; const ASessionId: string): string;
@@ -1101,9 +1101,8 @@ type
constructor Create(const AWebModule: TWebModule; const AConfigAction: TProc = nil;
const ACustomLogger: ILogWriter = nil); reintroduce;
destructor Destroy; override;
-
- function GetSessionBySessionId(const ASessionId: string): TWebSession;
function TryGetProtocolFilter(var ProtocolFilter: T): Boolean;
+ function GetSessionBySessionId(const ASessionId: string): TMVCWebSession;
{ webcontext events}
procedure OnWebContextCreate(const WebContextCreateEvent: TWebContextCreateEvent);
@@ -1153,43 +1152,77 @@ type
property message: string read FMessage write FMessage;
end;
+
+ // std responses
+
+ IMVCResponse = interface
+ ['{9DFEC741-EE38-4AC9-9C2C-9EA0D15D08D5}']
+ function GetData: TObject;
+ function GetMessage: string;
+ function GetReasonString: string;
+ function GetStatusCode: Integer;
+ function GetIgnoredList: TMVCIgnoredList;
+ property StatusCode: Integer read GetStatusCode;
+ property ReasonString: string read GetReasonString;
+ property Message: string read GetMessage;
+ property Data: TObject read GetData;
+ end;
+
[MVCNameCase(ncLowerCase)]
- TMVCResponse = class
+ TMVCResponse = class(TInterfacedObject, IMVCResponse)
private
- FStatusCode: Integer;
- FReasonString: string;
- FMessage: string;
+ fStatusCode: Integer;
+ fReasonString: string;
+ fMessage: string;
fDataObject: TObject;
+ fIgnoredList: TMVCIgnoredList;
+ fObjectDictionary: IMVCObjectDictionary;
+ function GetData: TObject;
+ function GetMessage: string;
+ function GetReasonString: string;
+ function GetStatusCode: Integer;
+ procedure SetData(const Value: TObject);
+ procedure SetMessage(const Value: string);
+ procedure SetReasonString(const Value: string);
+ procedure SetStatusCode(const Value: Integer);
+ function GetObjectDictionary: IMVCObjectDictionary;
+ procedure SetObjectDictionary(const Value: IMVCObjectDictionary);
protected
- { protected declarations }
- public
constructor Create; overload; virtual;
- constructor Create(AStatusCode: Integer; AReasonString: string; AMessage: string); overload;
+ public
+ constructor Create(AStatusCode: Integer; AMessage: string; AReasonString: string = ''); overload;
+ constructor Create(AStatusCode: Integer; AData: TObject; AReasonString: string = ''); overload;
+ constructor Create(AStatusCode: Integer; AObjectDictionary: IMVCObjectDictionary; AReasonString: string = ''); overload;
destructor Destroy; override;
- property StatusCode: Integer read FStatusCode write FStatusCode;
- property ReasonString: string read FReasonString write FReasonString;
- property Message: string read FMessage write FMessage;
- property Data: TObject read fDataObject write fDataObject;
+ function GetIgnoredList: TMVCIgnoredList;
+ [MVCDoNotSerialize]
+ property StatusCode: Integer read GetStatusCode write SetStatusCode;
+ [MVCDoNotSerialize]
+ property ReasonString: string read GetReasonString write SetReasonString;
+ property Message: string read GetMessage write SetMessage;
+ property Data: TObject read GetData write SetData;
+ property ObjectDictionary: IMVCObjectDictionary read GetObjectDictionary write SetObjectDictionary;
end;
[MVCNameCase(ncLowerCase)]
TMVCErrorResponse = class(TMVCResponse)
private
- FClassname: string;
- FItems: TObjectList;
- FAppErrorCode: Integer;
- FDetailedMessage: string;
+ fClassname: string;
+ fItems: TObjectList;
+ fAppErrorCode: Integer;
+ fDetailedMessage: string;
procedure SetAppErrorCode(const Value: Integer);
public
constructor Create; override;
destructor Destroy; override;
- property Classname: string read FClassname write FClassname;
- property DetailedMessage: string read FDetailedMessage write FDetailedMessage;
- property AppErrorCode: Integer read FAppErrorCode write SetAppErrorCode;
+ property Classname: string read fClassname write fClassname;
+ property DetailedMessage: string read fDetailedMessage write fDetailedMessage;
+ property AppErrorCode: Integer read fAppErrorCode write SetAppErrorCode;
[MVCListOf(TMVCErrorResponseItem)]
- property Items: TObjectList read FItems;
+ property Items: TObjectList read fItems;
end;
+ // end - std responses
TMVCBaseViewEngine = class(TMVCBase)
@@ -1224,7 +1257,13 @@ type
function IsShuttingDown: Boolean;
procedure EnterInShutdownState;
function CreateResponse(const StatusCode: UInt16; const ReasonString: string;
- const Message: string = ''): TMVCResponse;
+ const Message: string = ''): TMVCResponse; deprecated 'Use MVCResponse()';
+
+// std responses
+function MVCResponse(AStatusCode: Integer; AMessage: string = ''; AReasonString: string = ''): IMVCResponse; overload;
+function MVCResponse(AStatusCode: Integer; AData: TObject; AReasonString: string = ''): IMVCResponse; overload;
+function MVCResponse(AStatusCode: Integer; AObjectDictionary: IMVCObjectDictionary; AReasonString: string = ''): IMVCResponse; overload;
+// end - std responses
implementation
@@ -1992,7 +2031,7 @@ begin
Result := (not UserName.IsEmpty) and (LoggedSince > 0);
end;
-function TUser.LoadFromSession(const AWebSession: TWebSession): Boolean;
+function TUser.LoadFromSession(const AWebSession: TMVCWebSession): Boolean;
var
SerObj: string;
Pieces: TArray;
@@ -2016,7 +2055,7 @@ begin
end;
end;
-procedure TUser.SaveToSession(const AWebSession: TWebSession);
+procedure TUser.SaveToSession(const AWebSession: TMVCWebSession);
var
LRoles: string;
begin
@@ -2044,9 +2083,9 @@ end;
{ TWebContext }
function TWebContext.AddSessionToTheSessionList(const ASessionType, ASessionId: string;
- const ASessionTimeout: Integer): TWebSession;
+ const ASessionTimeout: Integer): TMVCWebSession;
var
- Session: TWebSession;
+ Session: TMVCWebSession;
begin
if (Trim(ASessionType) = EmptyStr) then
raise EMVCException.Create('Empty Session Type');
@@ -2218,16 +2257,35 @@ begin
Result := FRequest.ParamsTable;
end;
-function TWebContext.GetWebSession: TWebSession;
+function TWebContext.GetWebSession: TMVCWebSession;
+var
+ lSessionIDFromRequest: string;
+ lSessionType: String;
begin
if not Assigned(FWebSession) then
begin
- FWebSession := TMVCEngine.GetCurrentSession(
- TMVCEngine.ExtractSessionIdFromWebRequest(FRequest.RawWebRequest), False);
+ lSessionIDFromRequest := TMVCEngine.ExtractSessionIdFromWebRequest(FRequest.RawWebRequest);
+ FWebSession := TMVCEngine.GetCurrentSession(lSessionIDFromRequest, False);
if not Assigned(FWebSession) then
- SessionStart
+ begin
+ lSessionType := Config[TMVCConfigKey.SessionType];
+ if not TMVCSessionFactory.GetInstance.TryFindSessionID(lSessionType, lSessionIDFromRequest) then
+ begin
+ SessionStart(lSessionType);
+ end
+ else
+ begin
+ FWebSession := AddSessionToTheSessionList(
+ lSessionType,
+ lSessionIDFromRequest,
+ StrToInt(Config[TMVCConfigKey.SessionTimeout]));
+ TMVCEngine.SendSessionCookie(Self, FWebSession.SessionId);
+ end;
+ end
else
+ begin
TMVCEngine.SendSessionCookie(Self, FWebSession.SessionId);
+ end;
end;
Result := FWebSession;
Result.MarkAsUsed;
@@ -2255,14 +2313,14 @@ begin
Result := FSessionMustBeClose;
end;
-procedure TWebContext.SessionStart;
+procedure TWebContext.SessionStart(const SessionType: String);
var
ID: string;
begin
if not Assigned(FWebSession) then
begin
ID := TMVCEngine.SendSessionCookie(Self);
- FWebSession := AddSessionToTheSessionList(Config[TMVCConfigKey.SessionType], ID,
+ FWebSession := AddSessionToTheSessionList(SessionType, ID,
StrToInt64(Config[TMVCConfigKey.SessionTimeout]));
FIsSessionStarted := True;
FSessionMustBeClose := False;
@@ -2305,10 +2363,20 @@ begin
begin
raise EMVCSessionExpiredException.Create('Session not started');
end;
+
GlobalSessionList.Remove(SId);
+
if SId <> '' then
begin
FWebSession := nil;
+ try
+ TMVCSessionFactory.GetInstance.TryDeleteSessionID(Config[TMVCConfigKey.SessionType], SId);
+ except
+ on E: Exception do
+ begin
+ LogException(E, 'Cannot delete session file for sessionid: ' + SId);
+ end;
+ end;
end;
finally
TMonitor.Exit(GlobalSessionList);
@@ -2446,7 +2514,6 @@ begin
{end - filters}
FControllers := TObjectList.Create(True);
FSavedOnBeforeDispatch := nil;
-
WebRequestHandler.CacheConnections := True;
WebRequestHandler.MaxConnections := 4096;
@@ -2569,66 +2636,6 @@ begin
end;
end;
-//procedure TMVCEngine.ExecuteAfterControllerActionMiddleware(const AContext: TWebContext;
-// const AControllerQualifiedClassName: string; const AActionName: string;
-// const AHandled: Boolean);
-//var
-// I: Integer;
-//begin
-// for I := 0 to FMiddlewares.Count - 1 do
-// begin
-// FMiddlewares[I].OnAfterControllerAction(AContext, AControllerQualifiedClassName, AActionName, AHandled);
-// end;
-//end;
-
-//procedure TMVCEngine.ExecuteAfterRoutingMiddleware(const AContext: TWebContext;
-// const AHandled: Boolean);
-//var
-// I: Integer;
-//begin
-// for I := 0 to FMiddlewares.Count - 1 do
-// begin
-// FMiddlewares[I].OnAfterRouting(AContext, AHandled);
-// end;
-//end;
-
-//procedure TMVCEngine.ExecuteBeforeControllerActionMiddleware(const AContext: TWebContext;
-// const AControllerQualifiedClassName: string; const AActionName: string; var AHandled: Boolean);
-//var
-// Middleware: IMVCMiddleware;
-//begin
-// if not AHandled then
-// begin
-// for Middleware in FMiddlewares do
-// begin
-// Middleware.OnBeforeControllerAction(AContext, AControllerQualifiedClassName, AActionName,
-// AHandled);
-// if AHandled then
-// begin
-// Break;
-// end;
-// end;
-// end;
-//end;
-
-//procedure TMVCEngine.ExecuteBeforeRoutingMiddleware(const AContext: TWebContext;
-// var AHandled: Boolean);
-//var
-// Middleware: IMVCMiddleware;
-//begin
-// if not AHandled then
-// begin
-// for Middleware in FMiddlewares do
-// begin
-// Middleware.OnBeforeRouting(AContext, AHandled);
-// if AHandled then
-// begin
-// Break;
-// end;
-// end;
-// end;
-//end;
-
class function TMVCEngine.ExtractSessionIdFromWebRequest(const AWebRequest: TWebRequest): string;
begin
Result := AWebRequest.CookieFields.Values[TMVCConstants.SESSION_TOKEN_NAME];
@@ -2642,8 +2649,11 @@ begin
FWebModule.BeforeDispatch := OnBeforeDispatch;
end;
-class function TMVCEngine.GetCurrentSession(const ASessionId: string; const ARaiseExceptionIfExpired: Boolean): TWebSession;
-var lSessionList: TObjectDictionary;
+class function TMVCEngine.GetCurrentSession(
+ const ASessionId: string;
+ const ARaiseExceptionIfExpired: Boolean): TMVCWebSession;
+var
+ lSessionList: TObjectDictionary;
begin
Result := nil;
lSessionList := GlobalSessionList;
@@ -2677,7 +2687,7 @@ begin
end;
end;
-function TMVCEngine.GetSessionBySessionId(const ASessionId: string): TWebSession;
+function TMVCEngine.GetSessionBySessionId(const ASessionId: string): TMVCWebSession;
begin
Result := TMVCEngine.GetCurrentSession(ASessionId, False);
if Assigned(Result) then
@@ -2866,10 +2876,14 @@ begin
end;
class function TMVCEngine.SendSessionCookie(const AContext: TWebContext): string;
-var SId: string;
+var
+ SId: string;
begin
- SId := StringReplace(StringReplace(StringReplace('DT' + GUIDToString(TGUID.NewGuid), '}', '', []),
- '{', '', []), '-', '', [rfReplaceAll]);
+ SId := StringReplace(StringReplace(StringReplace(
+ 'DT' + GUIDToString(TGUID.NewGuid) + GUIDToString(TGUID.NewGuid),
+ '}', '', [rfReplaceAll]),
+ '{', '', [rfReplaceAll]),
+ '-', '', [rfReplaceAll]);
Result := SendSessionCookie(AContext, SId);
end;
@@ -3126,7 +3140,7 @@ begin
Result := Context.Request.GetHeader('If-Match');
end;
-function TMVCController.GetSession: TWebSession;
+function TMVCController.GetSession: TMVCWebSession;
begin
Result := GetContext.Session;
end;
@@ -3372,8 +3386,9 @@ begin
GetContext.Response.RawWebResponse.FreeContentStream := True;
end;
-function TMVCRenderer.Serializer(const AContentType: string;
-const ARaiseExceptionIfNotExists: Boolean): IMVCSerializer;
+function TMVCRenderer.Serializer(
+ const AContentType: string;
+ const ARaiseExceptionIfNotExists: Boolean): IMVCSerializer;
var lContentMediaType: string;
lContentCharSet: string;
begin
@@ -3530,6 +3545,7 @@ procedure TMVCRenderer.Render(
const AObject: IInterface;
const ASerializationAction: TMVCSerializationAction);
begin
+ {TODO -oDanieleT -cGeneral : Handle StatusCode}
Render(TObject(AObject), False, ASerializationAction);
end;
@@ -3759,8 +3775,8 @@ begin
begin
try
GetContext.Response.StatusCode := AResponse.StatusCode;
- GetContext.Response.ReasonString := HTTP_STATUS.ReasonStringFor(AResponse.StatusCode);
- Render(AResponse, False, stProperties);
+ GetContext.Response.ReasonString := AResponse.ReasonString;
+ Render(AResponse, False, stProperties, nil, AResponse.GetIgnoredList);
finally
if AOwns then
AResponse.Free;
@@ -3810,6 +3826,7 @@ constructor TMVCResponse.Create;
begin
inherited Create;
fDataObject := nil;
+ fMessage := '';
end;
constructor TMVCErrorResponse.Create;
@@ -3818,12 +3835,32 @@ begin
FItems := TObjectList.Create(True);
end;
-constructor TMVCResponse.Create(AStatusCode: Integer; AReasonString, AMessage: string);
+constructor TMVCResponse.Create(AStatusCode: Integer; AMessage: string; AReasonString: string);
begin
Create;
- StatusCode := AStatusCode;
- ReasonString := AReasonString;
- message := AMessage;
+ fStatusCode := AStatusCode;
+ fMessage := AMessage;
+ fReasonString := AReasonString;
+ fIgnoredList := ['Data', 'ObjectDictionary'];
+end;
+
+constructor TMVCResponse.Create(AStatusCode: Integer; AData: TObject; AReasonString: string);
+begin
+ Create;
+ fStatusCode := AStatusCode;
+ fDataObject := AData;
+ fReasonString := AReasonString;
+ fIgnoredList := ['Message', 'ObjectDictionary'];
+end;
+
+constructor TMVCResponse.Create(AStatusCode: Integer;
+ AObjectDictionary: IMVCObjectDictionary; AReasonString: string);
+begin
+ Create;
+ fStatusCode := AStatusCode;
+ fObjectDictionary := AObjectDictionary;
+ fReasonString := AReasonString;
+ fIgnoredList := ['Message', 'Data'];
end;
destructor TMVCResponse.Destroy;
@@ -3832,6 +3869,64 @@ begin
inherited;
end;
+function TMVCResponse.GetData: TObject;
+begin
+ Result := fDataObject;
+end;
+
+function TMVCResponse.GetIgnoredList: TMVCIgnoredList;
+begin
+ Result := fIgnoredList;
+end;
+
+function TMVCResponse.GetMessage: string;
+begin
+ Result := fMessage;
+end;
+
+function TMVCResponse.GetObjectDictionary: IMVCObjectDictionary;
+begin
+ Result := fObjectDictionary;
+end;
+
+function TMVCResponse.GetReasonString: string;
+begin
+ if fReasonString.IsEmpty then
+ Result := HTTP_STATUS.ReasonStringFor(fStatusCode)
+ else
+ Result := fReasonString;
+end;
+
+function TMVCResponse.GetStatusCode: Integer;
+begin
+ Result := fStatusCode;
+end;
+
+procedure TMVCResponse.SetData(const Value: TObject);
+begin
+ fDataObject := Value;
+end;
+
+procedure TMVCResponse.SetMessage(const Value: string);
+begin
+ fMessage := Value;
+end;
+
+procedure TMVCResponse.SetObjectDictionary(const Value: IMVCObjectDictionary);
+begin
+ fObjectDictionary := Value;
+end;
+
+procedure TMVCResponse.SetReasonString(const Value: string);
+begin
+ fReasonString := Value;
+end;
+
+procedure TMVCResponse.SetStatusCode(const Value: Integer);
+begin
+ fStatusCode := Value;
+end;
+
destructor TMVCErrorResponse.Destroy;
begin
FItems.Free;
@@ -4054,6 +4149,24 @@ procedure TCustomControllerFilter.SetNext(NextFilter: IControllerFilter);
begin
fNext := NextFilter;
end;
+//=======
+// std responses
+function MVCResponse(AStatusCode: Integer; AMessage: string; AReasonString: string): IMVCResponse; overload;
+begin
+ Result := TMVCResponse.Create(AStatusCode, AMessage, AReasonString);
+end;
+
+function MVCResponse(AStatusCode: Integer; AData: TObject; AReasonString: string): IMVCResponse; overload;
+begin
+ Result := TMVCResponse.Create(AStatusCode, AData, AReasonString);
+end;
+
+function MVCResponse(AStatusCode: Integer; AObjectDictionary: IMVCObjectDictionary; AReasonString: string): IMVCResponse; overload;
+begin
+ Result := TMVCResponse.Create(AStatusCode, AObjectDictionary, AReasonString);
+end;
+
+// end - std responses
initialization
diff --git a/unittests/general/Several/ActiveRecordTestsU.pas b/unittests/general/Several/ActiveRecordTestsU.pas
index d72553e7..4a2aecc1 100644
--- a/unittests/general/Several/ActiveRecordTestsU.pas
+++ b/unittests/general/Several/ActiveRecordTestsU.pas
@@ -70,12 +70,20 @@ type
[Test]
procedure TestSelectWithExceptions;
[Test]
+ procedure TestNamedQuerySQL;
+ [Test]
+ procedure TestNamedQuerySQLByBackEnd;
+ [Test]
procedure TestStore;
[Test]
procedure TestLifeCycle;
[Test]
procedure TestRQL;
[Test]
+ procedure TestNamedQueryRQL;
+ [Test]
+ procedure TestNamedQueryRQLWithExceptions;
+ [Test]
procedure TestRQLWithMVCNameAsAttribute;
[Test]
procedure TestRQLWithBoolean;
@@ -1170,6 +1178,68 @@ begin
Assert.AreEqual(Trunc(20 * 30), TMVCActiveRecord.Count(TCustomerWithLF));
end;
+procedure TTestActiveRecordBase.TestNamedQueryRQL;
+var
+ lCustomers: TObjectList;
+begin
+ Assert.AreEqual(Int64(0), TMVCActiveRecord.Count(TCustomer));
+ LoadData;
+ lCustomers := TMVCActiveRecord.SelectRQLByNamedQuery('CityRomeOrLondon', [], MAXINT);
+ try
+ Assert.AreEqual(240, lCustomers.Count);
+ for var lCustomer in lCustomers do
+ begin
+ Assert.IsMatch('^(Rome|London)$', lCustomer.City);
+ end;
+ finally
+ lCustomers.Free;
+ end;
+ TMVCActiveRecord.DeleteRQLByNamedQuery('CityRomeOrLondon', []);
+ Assert.AreEqual(Int64(0), TMVCActiveRecord.CountRQLByNamedQuery('CityRomeOrLondon', []));
+end;
+
+procedure TTestActiveRecordBase.TestNamedQueryRQLWithExceptions;
+begin
+ Assert.WillRaiseWithMessage(
+ procedure
+ begin
+ TMVCActiveRecord.SelectRQLByNamedQuery('WrongQueryName', [1,2,3], MAXINT);
+ end, nil, 'NamedRQLQuery not found: WrongQueryName');
+
+ Assert.WillRaiseWithMessage(
+ procedure
+ begin
+ TMVCActiveRecord.DeleteRQLByNamedQuery('WrongQueryName', []);
+ end, nil, 'NamedRQLQuery not found: WrongQueryName');
+end;
+
+procedure TTestActiveRecordBase.TestNamedQuerySQL;
+begin
+ Assert.AreEqual(Int64(0), TMVCActiveRecord.Count(TCustomer));
+ LoadData;
+ var lCustomers := TMVCActiveRecord.SelectByNamedQuery('ByTwoCities', ['Rome', 'London'], [ftString, ftString]);
+ try
+ Assert.AreEqual(240, lCustomers.Count);
+ for var lCustomer in lCustomers do
+ begin
+ Assert.IsMatch('^(Rome|London)$', lCustomer.City);
+ end;
+ finally
+ lCustomers.Free;
+ end;
+end;
+
+procedure TTestActiveRecordBase.TestNamedQuerySQLByBackEnd;
+begin
+ var lList := TMVCActiveRecord.SelectByNamedQuery('get_backend_name', [],[]);
+ try
+ Assert.AreEqual(1, lList.Count);
+ Assert.AreEqual(lList.First.GetBackEnd, lList.First.BackEndName);
+ finally
+ lList.Free;
+ end;
+end;
+
procedure TTestActiveRecordBase.TestNullables;
var
lTest: TNullablesTest;
diff --git a/unittests/general/Several/BOs.pas b/unittests/general/Several/BOs.pas
index 10aceae4..88ce22bb 100644
--- a/unittests/general/Several/BOs.pas
+++ b/unittests/general/Several/BOs.pas
@@ -101,6 +101,8 @@ const
type
[MVCTable('customers')]
+ [MVCNamedRQLQuery('CityRomeOrLondon','or(eq(City, "Rome"),eq(City, "London"))')]
+ [MVCNamedSQLQuery('ByTwoCities','select * from customers where city = ? or city = ?')]
TCustomer = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
@@ -661,6 +663,19 @@ type
destructor Destroy; override;
end;
+ [MVCEntityActions([eaRetrieve])]
+ [MVCNamedSQLQuery('get_backend_name', 'select ''firebird'' backendname from rdb$database', TMVCActiveRecordBackEnd.FirebirdSQL)]
+ [MVCNamedSQLQuery('get_backend_name', 'select ''postgresql'' backendname', TMVCActiveRecordBackEnd.PostgreSQL)]
+ [MVCNamedSQLQuery('get_backend_name', 'select ''sqlite'' backendname', TMVCActiveRecordBackEnd.SQLite)]
+ TDummyEntity = class(TMVCActiveRecord)
+ private
+ [MVCTableField('backendname')]
+ FBackEndName: String;
+ procedure SetBackEndName(const Value: String);
+ public
+ property BackEndName: String read FBackEndName write SetBackEndName;
+ end;
+
function GetMyObject: TMyObject;
function GetMyObjectWithTValue: TMyObjectWithTValue;
function GetMyObjectWithStream: TMyStreamObject;
@@ -1432,6 +1447,13 @@ begin
end;
+{ TDummyEntity }
+
+procedure TDummyEntity.SetBackEndName(const Value: String);
+begin
+ FBackEndName := Value;
+end;
+
initialization
ActiveRecordMappingRegistry.AddEntity('customers', TCustomer);
diff --git a/unittests/general/Several/FrameworkTestsU.pas b/unittests/general/Several/FrameworkTestsU.pas
index 7d2d3629..e96c9a44 100644
--- a/unittests/general/Several/FrameworkTestsU.pas
+++ b/unittests/general/Several/FrameworkTestsU.pas
@@ -38,43 +38,6 @@ uses
type
- [TestFixture]
- TTestMappers = class(TObject)
- protected
- [Test]
- procedure SameFishesDataSet(ds, ds2: TDataSet);
-
- public
- // procedure TestObjectToJSONObject;
- // procedure TestObjectListToJSONArray;
- // procedure TestObjectToJSONObject_Generics;
- // procedure TestWrappedListToJSONArray;
- // procedure TestJSONObjectToObjectAndBack;
- // procedure TestLoadJSONObjectToObjectAndBack;
- // procedure TestSerializeUsingProperties;
- // procedure TestSerializeUsingFields;
- // procedure TestSerializeUsingFieldsComplexObject;
- // procedure TestSerializeUsingFieldsComplexObject2;
- // procedure TestSerializeUsingFieldsWithNotExixtentPropetyInJSONObject;
- // procedure TestComplexObjectToJSONObjectAndBack;
- // procedure TestComplexObjectToJSONObjectAndBackWithNilReference;
- // procedure TestDataSetToJSONObject;
- // procedure TestDataSetToJSONObjectWithNulls;
- // procedure TestDataSetToJSONObjectFieldPolicyLowerCase;
- // procedure TestDataSetToJSONObjectFieldPolicyUpperCase;
- // procedure TestDataSetToJSONObjectFieldPolicyAsIsCase;
- // procedure TestDataSetToJSONArray;
- // procedure TestObjectToJSONObjectAndBackWithStringStreamUTF16;
- // procedure TestObjectToJSONObjectAndBackWithStringStreamUTF8;
- // procedure TestObjectToJSONObjectAndBackWithStream;
- // procedure TestJSONArrayToObjectListNoGenerics;
- // procedure TestJSONArrayToObjectListNoGenericsWrappedList;
- // procedure TestCheckMapperSerializeAsStringIsEmptyStrIfObjIsNil;
- // procedure TestJSONObjectToObjectWithNullInJSONString;
- // procedure TestJSONObjectStringToObject;
- // procedure TestJSONObjectStringToObjectWithWrongJSON;
- end;
-
[TestFixture]
TTestRouting = class(TObject)
private
@@ -381,18 +344,6 @@ begin
end;
end;
-procedure TTestMappers.SameFishesDataSet(ds, ds2: TDataSet);
-begin
- Assert.areEqual(ds.FieldByName('Species No').AsInteger, ds2.FieldByName('Species No').AsInteger);
- Assert.areEqual(ds.FieldByName('Category').AsString, ds2.FieldByName('Category').AsString);
- Assert.areEqual(ds.FieldByName('Common_Name').AsString, ds2.FieldByName('Common_Name').AsString);
- Assert.areEqual(ds.FieldByName('Species Name').AsString, ds2.FieldByName('Species Name').AsString);
- Assert.areEqual(ds.FieldByName('Length (cm)').AsString, ds2.FieldByName('Length (cm)').AsString);
- Assert.areEqual(ds.FieldByName('Length_In').AsInteger, ds2.FieldByName('Length_In').AsInteger);
- Assert.areEqual(ds.FieldByName('Notes').AsString, ds2.FieldByName('Notes').AsString);
- Assert.areEqual(ds.FieldByName('Graphic').AsString, ds2.FieldByName('Graphic').AsString);
-end;
-
procedure TTestRouting.SetUp;
begin
FControllers := TObjectList.Create;
diff --git a/unittests/general/Several/LiveServerTestU.pas b/unittests/general/Several/LiveServerTestU.pas
index 1169cf19..773b63d2 100644
--- a/unittests/general/Several/LiveServerTestU.pas
+++ b/unittests/general/Several/LiveServerTestU.pas
@@ -298,6 +298,22 @@ type
[Test]
procedure TestViewDataViewDataSet;
+ // test functional actions
+ [Test]
+ procedure TestFuncActionGetSingleRecord;
+
+ [Test]
+ procedure TestFuncActionGetMultipleRecords;
+
+ [Test]
+ procedure TestFuncActionGetDatasetSingle;
+
+ [Test]
+ procedure TestFuncActionGetDatasetMultiple;
+
+ [Test]
+ procedure TestFuncActionGetComplexObject;
+
// test issues
[Test]
[Category('renders')]
@@ -1068,12 +1084,11 @@ var
begin
res := RESTClient.Get('/exception/emvcexception1');
Assert.areEqual(HTTP_STATUS.InternalServerError, res.StatusCode);
+ Assert.areEqual('Internal Server Error', res.StatusText);
lJSON := StrToJSONObject(res.Content);
try
Assert.areEqual('message', lJSON.S['message'], lJSON.ToJSON());
Assert.areEqual('EMVCException', lJSON.S['classname'], lJSON.ToJSON());
- Assert.areEqual(500, lJSON.I['statuscode'], lJSON.ToJSON());
- Assert.areEqual('Internal Server Error', lJSON.S['reasonstring'], lJSON.ToJSON());
Assert.areEqual(0, lJSON.A['items'].Count, lJSON.ToJSON());
Assert.isTrue(lJSON.IsNull('data'), lJSON.ToJSON());
finally
@@ -1089,12 +1104,11 @@ var
begin
res := RESTClient.Get('/exception/emvcexception2');
Assert.areEqual(HTTP_STATUS.BadRequest, res.StatusCode);
+ Assert.areEqual('Bad Request', res.StatusText);
lJSON := StrToJSONObject(res.Content);
try
Assert.areEqual('message', lJSON.S['message'], lJSON.ToJSON());
Assert.areEqual('EMVCException', lJSON.S['classname'], lJSON.ToJSON());
- Assert.areEqual(HTTP_STATUS.BadRequest, lJSON.I['statuscode'], lJSON.ToJSON());
- Assert.areEqual('Bad Request', lJSON.S['reasonstring'], lJSON.ToJSON());
Assert.areEqual(0, lJSON.A['items'].Count, lJSON.ToJSON());
Assert.isTrue(lJSON.IsNull('data'), lJSON.ToJSON());
finally
@@ -1109,12 +1123,11 @@ var
begin
res := RESTClient.Get('/exception/emvcexception3');
Assert.areEqual(HTTP_STATUS.Created, res.StatusCode);
+ Assert.areEqual('Created', res.StatusText);
lJSON := StrToJSONObject(res.Content);
try
Assert.areEqual('message', lJSON.S['message'], lJSON.ToJSON());
Assert.areEqual('EMVCException', lJSON.S['classname'], lJSON.ToJSON());
- Assert.areEqual(HTTP_STATUS.Created, lJSON.I['statuscode'], lJSON.ToJSON());
- Assert.areEqual('Created', lJSON.S['reasonstring'], lJSON.ToJSON());
Assert.areEqual(999, lJSON.I['apperrorcode'], lJSON.ToJSON());
Assert.areEqual(0, lJSON.A['items'].Count, lJSON.ToJSON());
Assert.isTrue(lJSON.IsNull('data'), lJSON.ToJSON());
@@ -1130,13 +1143,12 @@ var
begin
res := RESTClient.Get('/exception/emvcexception4');
Assert.areEqual(HTTP_STATUS.Created, res.StatusCode);
+ Assert.areEqual('Created', res.StatusText);
lJSON := StrToJSONObject(res.Content);
try
Assert.areEqual('message', lJSON.S['message'], lJSON.ToJSON());
Assert.areEqual('detailedmessage', lJSON.S['detailedmessage'], lJSON.ToJSON());
Assert.areEqual('EMVCException', lJSON.S['classname'], lJSON.ToJSON());
- Assert.areEqual(HTTP_STATUS.Created, lJSON.I['statuscode'], lJSON.ToJSON());
- Assert.areEqual('Created', lJSON.S['reasonstring'], lJSON.ToJSON());
Assert.areEqual(999, lJSON.I['apperrorcode'], lJSON.ToJSON());
Assert.areEqual(2, lJSON.A['items'].Count, lJSON.ToJSON());
Assert.areEqual('erritem1', lJSON.A['items'].O[0].S['message'], lJSON.ToJSON());
@@ -1443,6 +1455,118 @@ begin
Assert.areEqual('This is a TEXT file', lRes.Content, '/static/folder1.html');
end;
+procedure TServerTest.TestFuncActionGetComplexObject;
+var
+ c1: IMVCRESTClient;
+ lRes: IMVCRESTResponse;
+begin
+ c1 := TMVCRESTClient.New.BaseURL(TEST_SERVER_ADDRESS, 9999);
+ lRes := c1.Get('/api/v1/actionresult/complex');
+ Assert.areEqual(200, lRes.StatusCode);
+ var lJSON := lRes.ToJSONObject;
+ try
+ Assert.AreEqual(3, lJSON.Count);
+ Assert.IsTrue(lJSON.Types['value'] = jdtInt);
+ Assert.IsTrue(lJSON.Types['person'] = jdtObject);
+ Assert.IsTrue(lJSON.Types['people'] = jdtArray);
+ Assert.AreEqual(6, lJSON.O['person'].Count);
+ Assert.AreEqual(3, lJSON.A['people'].Count);
+ Assert.AreEqual(6, lJSON.A['people'][0].ObjectValue.Count);
+ Assert.AreEqual(6, lJSON.A['people'][1].ObjectValue.Count);
+ Assert.AreEqual(6, lJSON.A['people'][2].ObjectValue.Count);
+ finally
+ lJSON.Free;
+ end;
+end;
+
+procedure TServerTest.TestFuncActionGetDatasetMultiple;
+var
+ c1: IMVCRESTClient;
+ lRes: IMVCRESTResponse;
+begin
+ c1 := TMVCRESTClient.New.BaseURL(TEST_SERVER_ADDRESS, 9999);
+ lRes := c1.Get('/api/v1/actionresult/dataset/multiple');
+ Assert.areEqual(200, lRes.StatusCode);
+ var lJSON := lRes.ToJSONObject;
+ try
+ Assert.AreEqual(2, lJSON.Count);
+ Assert.IsTrue(lJSON.Contains('ds1'));
+ Assert.IsTrue(lJSON.Contains('ds2'));
+ Assert.AreEqual(15, lJSON.A['ds1'].Count);
+ Assert.AreEqual(15, lJSON.A['ds2'].Count);
+ finally
+ lJSON.Free;
+ end;
+end;
+
+procedure TServerTest.TestFuncActionGetDatasetSingle;
+var
+ c1: IMVCRESTClient;
+ lRes: IMVCRESTResponse;
+begin
+ c1 := TMVCRESTClient.New.BaseURL(TEST_SERVER_ADDRESS, 9999);
+ lRes := c1.Get('/api/v1/actionresult/dataset/single');
+ Assert.areEqual(200, lRes.StatusCode);
+ var lJSON := lRes.ToJSONArray;
+ try
+ Assert.AreEqual(15, lJSON.Count);
+ for var I := 0 to lJSON.Count - 1 do
+ begin
+ Assert.IsTrue(lJSON[I].Typ = jdtObject);
+ Assert.AreEqual(12, lJSON[I].ObjectValue.Count);
+ end;
+ finally
+ lJSON.Free;
+ end;
+end;
+
+procedure TServerTest.TestFuncActionGetMultipleRecords;
+var
+ c1: IMVCRESTClient;
+ lRes: IMVCRESTResponse;
+begin
+ c1 := TMVCRESTClient.New.BaseURL(TEST_SERVER_ADDRESS, 9999);
+ lRes := c1.Get('/api/v1/actionresult/records/multiple');
+ Assert.areEqual(200, lRes.StatusCode);
+ var lJSON := lRes.ToJSONArray;
+ try
+ Assert.AreEqual(3, lJSON.Count);
+
+ Assert.AreEqual('Daniele', lJSON[0].S['firstName']);
+ Assert.AreEqual('Teti', lJSON[0].S['lastName']);
+ Assert.AreEqual(20, lJSON[0].I['age']);
+
+ Assert.AreEqual('Daniele', lJSON[1].S['firstName']);
+ Assert.AreEqual('Teti', lJSON[1].S['lastName']);
+ Assert.AreEqual(30, lJSON[1].I['age']);
+
+ Assert.AreEqual('Daniele', lJSON[2].S['firstName']);
+ Assert.AreEqual('Teti', lJSON[2].S['lastName']);
+ Assert.AreEqual(40, lJSON[2].I['age']);
+ finally
+ lJSON.Free;
+ end;
+end;
+
+procedure TServerTest.TestFuncActionGetSingleRecord;
+var
+ c1: IMVCRESTClient;
+ lRes: IMVCRESTResponse;
+begin
+ c1 := TMVCRESTClient.New.BaseURL(TEST_SERVER_ADDRESS, 9999);
+ lRes := c1.Get('/api/v1/actionresult/records/single');
+ Assert.areEqual(200, lRes.StatusCode);
+ var lJSON := lRes.ToJSONObject;
+ try
+ Assert.AreEqual(3, lJSON.Count);
+ Assert.AreEqual('Daniele', lJSON.S['firstName']);
+ Assert.AreEqual('Teti', lJSON.S['lastName']);
+ Assert.AreEqual(99, lJSON.I['age']);
+ finally
+ lJSON.Free;
+ end;
+end;
+
procedure TServerTest.TestGetImagePng;
var
c1: IMVCRESTClient;
diff --git a/unittests/general/TestServer/TestServerControllerU.pas b/unittests/general/TestServer/TestServerControllerU.pas
index b4b8812b..fd7195dd 100644
--- a/unittests/general/TestServer/TestServerControllerU.pas
+++ b/unittests/general/TestServer/TestServerControllerU.pas
@@ -34,7 +34,8 @@ uses
FireDAC.Comp.Client,
System.Generics.Collections,
Data.DB,
- BusinessObjectsU;
+ BusinessObjectsU, MVCFramework.Serializer.Commons, System.Classes,
+ System.UITypes;
type
@@ -46,9 +47,10 @@ type
fDataSet: TFDMemTable;
protected
procedure MVCControllerAfterCreate; override;
- function GetDataSet: TDataSet;
procedure MVCControllerBeforeDestroy; override;
public
+ class function GetDataSet: TDataSet;
+
[MVCPath('/req/with/params/($par1)/($par2)/($par3)')]
[MVCHTTPMethod([httpGET, httpDELETE])]
procedure ReqWithParams;
@@ -412,6 +414,117 @@ type
procedure Action1or2;
end;
+
+// action result types
+ [MVCNameCase(ncLowerCase)]
+ TSum = class
+ private
+ fValue: Integer;
+ public
+ property Value: Integer read fValue write fValue;
+ end;
+
+ [MVCNameCase(ncLowerCase)]
+ TComplexObject = class
+ private
+ fValue: Integer;
+ FPeople: TPeople;
+ FPerson: TPerson;
+ procedure SetPeople(const Value: TPeople);
+ procedure SetPerson(const Value: TPerson);
+ public
+ destructor Destroy; override;
+ property Value: Integer read fValue write fValue;
+ property Person: TPerson read FPerson write SetPerson;
+ property People: TPeople read FPeople write SetPeople;
+ end;
+
+ [MVCNameCase(ncCamelCase)]
+ TPersonRec = record
+ FirstName, LastName: String;
+ Age: Integer;
+ class function Create: TPersonRec; static;
+ end;
+// action result types - end
+
+ [MVCPath('/api/v1/actionresult')]
+ TTestActionResultController = class(TMVCController)
+ public
+ { actions returning records }
+ [MVCPath('/sums/($a)/($b)')]
+ [MVCHTTPMethod([httpGET])]
+ function GetObject(a,b: Integer): TSum;
+
+ [MVCPath('/records/single')]
+ function GetSingleRecord: TPersonRec;
+
+ [MVCPath('/records/multiple')]
+ function GetMultipleRecords: TArray;
+
+ [MVCPath('/complex')]
+ [MVCHTTPMethod([httpGET])]
+ function GetComplexObject: TComplexObject;
+
+ [MVCPath('/people')]
+ [MVCHTTPMethod([httpGET])]
+ function GetPeople: TObjectList;
+
+ [MVCPath('/people/($id)')]
+ [MVCHTTPMethod([httpGET])]
+ function GetPerson(id: Integer): IPerson;
+
+ [MVCPath('/photo')]
+ [MVCHTTPMethod([httpGET])]
+ function GetPhoto: TStream;
+
+ [MVCPath('/string')]
+ [MVCHTTPMethod([httpGET])]
+ function GetString: String;
+
+ [MVCPath('/enum')]
+ [MVCHTTPMethod([httpGET])]
+ function GetEnum: TFontStyle;
+
+ [MVCPath('/bool')]
+ [MVCHTTPMethod([httpGET])]
+ function GetBool: Boolean;
+
+ [MVCPath('/float')]
+ [MVCHTTPMethod([httpGET])]
+ function GetFloat: Double;
+
+ [MVCPath('/strdict')]
+ [MVCHTTPMethod([httpGET])]
+ function GetStrDict: TMVCStringDictionary;
+
+ [MVCPath('/TSimpleRecord')]
+ [MVCHTTPMethod([httpGET])]
+ function GetTSimpleRecord: TSimpleRecord;
+
+ [MVCPath('/ArrayOf/TSimpleRecord')]
+ [MVCHTTPMethod([httpGET])]
+ function GetArrayOfTSimpleRecord: TArray;
+
+ [MVCPath('/TComplexRecord')]
+ [MVCHTTPMethod([httpGET])]
+ function GetTComplexRecord: TComplexRecord;
+
+ [MVCPath('/ArrayOf/TComplexRecord')]
+ [MVCHTTPMethod([httpGET])]
+ function GetArrayOfTComplexRecord: TComplexRecordArray;
+
+ [MVCPath('/dataset/single')]
+ [MVCHTTPMethod([httpGET])]
+ function GetDataSetSingle: TDataSet;
+
+ [MVCPath('/dataset/multiple')]
+ [MVCHTTPMethod([httpGET])]
+ function GetDataSetMultiple: IMVCObjectDictionary;
+
+ end;
+
+
+
implementation
uses
@@ -419,11 +532,9 @@ uses
System.JSON,
Web.HTTPApp,
Generics.Collections,
- MVCFramework.Serializer.Commons,
MVCFramework.Serializer.Defaults,
MVCFramework.DuckTyping,
- System.IOUtils,
- System.Classes, MVCFramework.Tests.Serializer.Entities;
+ System.IOUtils, MVCFramework.Tests.Serializer.Entities, System.DateUtils;
{ TTestServerController }
@@ -512,7 +623,7 @@ begin
end;
-function TTestServerController.GetDataSet: TDataSet;
+class function TTestServerController.GetDataSet: TDataSet;
begin
Result := TFDMemTable.Create(nil);
TFDMemTable(Result).LoadFromFile(TPath.Combine(AppPath, 'customers.json'));
@@ -1226,4 +1337,150 @@ begin
Render(HTTP_STATUS.OK);
end;
+{ TTestActionResultController }
+
+function TTestActionResultController.GetArrayOfTComplexRecord: TComplexRecordArray;
+begin
+ SetLength(Result,3);
+ Result[0] := TComplexRecord.Create;
+ Result[1] := TComplexRecord.Create;
+ Result[2] := TComplexRecord.Create;
+
+ Result[0].StringProperty := 'item 0';
+ Result[1].StringProperty := 'item 1';
+ Result[2].StringProperty := 'item 2';
+end;
+
+function TTestActionResultController.GetArrayOfTSimpleRecord: TArray;
+begin
+ SetLength(Result, 3);
+ Result[0] := TSimpleRecord.Create;
+ Result[1] := TSimpleRecord.Create;
+ Result[2] := TSimpleRecord.Create;
+end;
+
+function TTestActionResultController.GetBool: Boolean;
+begin
+ Result := True;
+end;
+
+function TTestActionResultController.GetComplexObject: TComplexObject;
+begin
+ Result := TComplexObject.Create;
+ Result.Value := 1234;
+ Result.Person := TPerson.GetNew('Danielem', 'Teti', EncodeDate(1920,12,23), True);
+ Result.People := TPerson.GetList();
+end;
+
+function TTestActionResultController.GetDataSetMultiple: IMVCObjectDictionary;
+begin
+ Result :=
+ ObjectDict()
+ .Add('ds1', TTestServerController.GetDataSet)
+ .Add('ds2', TTestServerController.GetDataSet);
+end;
+
+function TTestActionResultController.GetDataSetSingle: TDataSet;
+begin
+ Result := TTestServerController.GetDataSet;
+end;
+
+function TTestActionResultController.GetEnum: TFontStyle;
+begin
+ Result := TFontStyle.fsBold;
+end;
+
+function TTestActionResultController.GetFloat: Double;
+begin
+ Result := 3.1415;
+end;
+
+function TTestActionResultController.GetMultipleRecords: TArray;
+begin
+ SetLength(Result, 3);
+ Result[0] := TPersonRec.Create;
+ Result[1] := TPersonRec.Create;
+ Result[2] := TPersonRec.Create;
+ Result[0].Age := 20;
+ Result[1].Age := 30;
+ Result[2].Age := 40;
+end;
+
+function TTestActionResultController.GetPeople: TObjectList;
+begin
+ Result := TPerson.GetList();
+end;
+
+function TTestActionResultController.GetPerson(id: Integer): IPerson;
+begin
+ Result := TInterfacedPerson.Create('Daniele Teti', 20, 2010);
+end;
+
+function TTestActionResultController.GetPhoto: TStream;
+begin
+ Context.Response.ContentType := TMVCMediaType.IMAGE_X_PNG;
+ Result := TFileStream.Create('sample.png', fmOpenRead or fmShareDenyNone);
+end;
+
+function TTestActionResultController.GetSingleRecord: TPersonRec;
+begin
+ Result := TPersonRec.Create;
+end;
+
+function TTestActionResultController.GetStrDict: TMVCStringDictionary;
+begin
+ Result := StrDict.Add('first_name','Daniele').Add('last_name','Teti');
+end;
+
+function TTestActionResultController.GetString: String;
+begin
+ Result := 'Hello World';
+end;
+
+function TTestActionResultController.GetTComplexRecord: TComplexRecord;
+begin
+ Result := TComplexRecord.Create;
+end;
+
+function TTestActionResultController.GetTSimpleRecord: TSimpleRecord;
+begin
+ Result := TSimpleRecord.Create;
+end;
+
+function TTestActionResultController.GetObject(a, b: Integer): TSum;
+begin
+ StatusCode := 201;
+ Context.Response.SetCustomHeader('X-CUSTOM-HEADER','CARBONARA');
+ Result := TSum.Create;
+ Result.Value := a + b;
+end;
+
+{ TComplexObject }
+
+destructor TComplexObject.Destroy;
+begin
+ FPerson.Free;
+ FPeople.Free;
+ inherited;
+end;
+
+procedure TComplexObject.SetPeople(const Value: TPeople);
+begin
+ FPeople := Value;
+end;
+
+procedure TComplexObject.SetPerson(const Value: TPerson);
+begin
+ FPerson := Value;
+end;
+
+{ TPersonRec }
+
+class function TPersonRec.Create: TPersonRec;
+begin
+ Result.FirstName := 'Daniele';
+ Result.LastName := 'Teti';
+ Result.Age := 99;
+end;
+
end.
diff --git a/unittests/general/TestServer/WebModuleUnit.pas b/unittests/general/TestServer/WebModuleUnit.pas
index 4c2f72a8..a746a3a4 100644
--- a/unittests/general/TestServer/WebModuleUnit.pas
+++ b/unittests/general/TestServer/WebModuleUnit.pas
@@ -93,6 +93,7 @@ begin
.AddController(TTestServerControllerActionFilters)
.AddController(TTestPrivateServerControllerCustomAuth)
.AddController(TTestMultiPathController)
+ .AddController(TTestActionResultController)
.AddController(TTestJSONRPCController, '/jsonrpc')
.AddController(TTestJSONRPCControllerWithGet, '/jsonrpcwithget')
.AddController(TMVCActiveRecordController,
diff --git a/unittests/general/UnitTestReports/dmvcframework_nunit_win32.xml b/unittests/general/UnitTestReports/dmvcframework_nunit_win32.xml
index dcb80048..32086969 100644
--- a/unittests/general/UnitTestReports/dmvcframework_nunit_win32.xml
+++ b/unittests/general/UnitTestReports/dmvcframework_nunit_win32.xml
@@ -1,407 +1,232 @@
-
+
-
+
-
+
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
@@ -409,10 +234,10 @@
-
+
-
-
+
+
@@ -422,19 +247,19 @@
-
-
-
+
+
+
-
-
+
+
-
+
@@ -493,127 +318,282 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -623,387 +603,438 @@
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
+
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unittests/general/UnitTestReports/dmvcframework_nunit_win64.xml b/unittests/general/UnitTestReports/dmvcframework_nunit_win64.xml
index df651f92..4575f70e 100644
--- a/unittests/general/UnitTestReports/dmvcframework_nunit_win64.xml
+++ b/unittests/general/UnitTestReports/dmvcframework_nunit_win64.xml
@@ -1,192 +1,358 @@
-
+
-
+
-
+
-
-
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -199,26 +365,332 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -230,15 +702,211 @@
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -248,8 +916,8 @@
-
-
+
+
@@ -259,17 +927,17 @@
-
-
+
+
-
+
-
+
@@ -330,212 +998,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
@@ -555,453 +1026,17 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-