New build system based on pyinvoke

This commit is contained in:
Daniele Teti 2019-01-08 12:48:27 +01:00
parent f64eebff6a
commit 8ed859b7d1
147 changed files with 6329 additions and 1371 deletions

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib/dmustache" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,4 @@
# 3.1.0 (lithium) breaking changes
- JSON-RPC Client Classes has been changed. Now they are interfaces based.
- JSON-RPC Server: Only public instance methods can be invoked.

201
LICENSE
View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

53
License.txt Normal file
View File

@ -0,0 +1,53 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

116
contrib/mwAnalytics.pas Normal file
View File

@ -0,0 +1,116 @@
unit mwAnalytics;
interface
uses
MVCFramework, MVCFramework.Logger, System.Classes;
type
IFileAnalytics = interface
['{C77426C4-1D34-4B3A-BD21-3C07B7E0B8BD}']
function GetRecentlyUsedAPI() : string;
function GetConsumeAPICount(ControllerName, ActionName : string) : Integer;
end;
TMVCAnalyticsMiddleware = class(TInterfacedObject, IMVCMiddleware, IFileAnalytics)
private
FAnalyticsFileName: string;
FAnalyticsFile: TStringList;
procedure SetAnalyticsFilename(const Value: string);
protected
procedure OnBeforeRouting(Context: TWebContext; var Handled: Boolean);
procedure OnAfterControllerAction(Context: TWebContext; const AActionNAme: string;
const Handled: Boolean);
procedure OnBeforeControllerAction(Context: TWebContext;
const AControllerQualifiedClassName: string; const AActionNAme: string; var Handled: Boolean);
public
property AnalyticsFilename: string read FAnalyticsFileName write SetAnalyticsFilename;
//Own Function
function GetRecentlyUsedAPI : string;
function GetConsumeAPICount(ControllerName, ActionName : string) : Integer;
end;
implementation
uses
System.SysUtils, System.JSON, REST.Json;
{ TMVCAnalyticsMiddleware }
function TMVCAnalyticsMiddleware.GetConsumeAPICount(ControllerName,
ActionName: string): Integer;
begin
Result := 5;
end;
function TMVCAnalyticsMiddleware.GetRecentlyUsedAPI: string;
begin
Result := 'Test'
end;
procedure TMVCAnalyticsMiddleware.OnAfterControllerAction(Context: TWebContext;
const AActionNAme: string; const Handled: Boolean);
begin
//Context.Response.Content := Context.Response.Content + '[][][]' ;
end;
procedure TMVCAnalyticsMiddleware.OnBeforeControllerAction(Context: TWebContext;
const AControllerQualifiedClassName, AActionNAme: string;
var Handled: Boolean);
var
Data : TJSONObject;
CSVFile : TextFile;
ApplicationPath : string;
begin
{AnalyticsFilename := 'analytics.json';
if not Assigned(FAnalyticsFile) then
raise Exception.Create('Analytics: Cannot read or write to file.');
Data := TJSONObject.Create;
Data.AddPair('TimeStamp', DateTimeToStr(Now));
Data.AddPair('IPAddress', Context.Request.ClientIp);
Data.AddPair('ControllerName', AControllerQualifiedClassName);
Data.AddPair('ActionName', AActionNAme);
FAnalyticsFile.Add(Data.ToJSON);
FAnalyticsFile.SaveToFile(FAnalyticsFileName);
Data.Free;}
//Context.Request;
ApplicationPath := ExtractFilePath(GetModuleName(hInstance));
AssignFile(CSVFile, ApplicationPath+'analytics.csv');
if not FileExists('analytics.csv') then
begin
Rewrite(CSVFile);
WriteLn(CSVFile, 'DateTime, IpAddress, ControllerName, ActionName, DomainName, Host');
end;
Append(CSVFile);
WriteLn(CSVFile, DateTimeToStr(Now), ',', Context.Request.ClientIp, ',', AControllerQualifiedClassName, ',',AActionNAme, ',' , Context.Request.RawWebRequest.Referer, ',', Context.Request.RawWebRequest.Host);
CloseFile(CSVFile);
end;
procedure TMVCAnalyticsMiddleware.OnBeforeRouting(Context: TWebContext;
var Handled: Boolean);
begin
end;
procedure TMVCAnalyticsMiddleware.SetAnalyticsFilename(const Value: string);
begin
// create the class if not there
if not Assigned(FAnalyticsFile) then
FAnalyticsFile := TStringList.Create;
// Create the file if it doesn't exist
if not FileExists(Value) then
FAnalyticsFile.SaveToFile(Value)
else
FAnalyticsFile.LoadFromFile(Value);
// assign the name
FAnalyticsFileName := Value;
end;
end.

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -36,7 +36,8 @@ requires
IndySystem,
IndyProtocols,
IndyCore,
dbrtl;
dbrtl,
dmvcframeworkRT;
contains
DMVC.Expert.CodeGen.NewControllerUnit in 'DMVC.Expert.CodeGen.NewControllerUnit.pas',
@ -51,7 +52,6 @@ contains
DMVC.Expert.NewUnitWizardEx in 'DMVC.Expert.NewUnitWizardEx.pas',
DMVC.Expert.ProjectWizardEx in 'DMVC.Expert.ProjectWizardEx.pas',
DMVC.Expert.Registration in 'DMVC.Expert.Registration.pas',
DMVC.Splash.Registration in 'DMVC.Splash.Registration.pas',
MVCFramework.Commons in '..\sources\MVCFramework.Commons.pas';
DMVC.Splash.Registration in 'DMVC.Splash.Registration.pas';
end.

View File

@ -161,6 +161,7 @@
<DCCReference Include="IndyProtocols.dcp"/>
<DCCReference Include="IndyCore.dcp"/>
<DCCReference Include="dbrtl.dcp"/>
<DCCReference Include="dmvcframeworkRT.dcp"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewControllerUnit.pas"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewDMVCProject.pas"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewProject.pas"/>
@ -178,7 +179,6 @@
<DCCReference Include="DMVC.Expert.ProjectWizardEx.pas"/>
<DCCReference Include="DMVC.Expert.Registration.pas"/>
<DCCReference Include="DMVC.Splash.Registration.pas"/>
<DCCReference Include="..\sources\MVCFramework.Commons.pas"/>
<RcItem Include="DMVC.Expert.NewProject.ico">
<ResourceType>ICON</ResourceType>
<ResourceId>DMVCNewProjectIcon</ResourceId>

View File

@ -36,7 +36,8 @@ requires
IndySystem,
IndyProtocols,
IndyCore,
dbrtl;
dbrtl,
dmvcframeworkRT;
contains
DMVC.Expert.CodeGen.NewControllerUnit in 'DMVC.Expert.CodeGen.NewControllerUnit.pas',
@ -51,7 +52,6 @@ contains
DMVC.Expert.NewUnitWizardEx in 'DMVC.Expert.NewUnitWizardEx.pas',
DMVC.Expert.ProjectWizardEx in 'DMVC.Expert.ProjectWizardEx.pas',
DMVC.Expert.Registration in 'DMVC.Expert.Registration.pas',
DMVC.Splash.Registration in 'DMVC.Splash.Registration.pas',
MVCFramework.Commons in '..\sources\MVCFramework.Commons.pas';
DMVC.Splash.Registration in 'DMVC.Splash.Registration.pas';
end.

View File

@ -126,6 +126,7 @@
<DCCReference Include="IndyProtocols.dcp"/>
<DCCReference Include="IndyCore.dcp"/>
<DCCReference Include="dbrtl.dcp"/>
<DCCReference Include="dmvcframeworkRT.dcp"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewControllerUnit.pas"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewDMVCProject.pas"/>
<DCCReference Include="DMVC.Expert.CodeGen.NewProject.pas"/>
@ -143,7 +144,6 @@
<DCCReference Include="DMVC.Expert.ProjectWizardEx.pas"/>
<DCCReference Include="DMVC.Expert.Registration.pas"/>
<DCCReference Include="DMVC.Splash.Registration.pas"/>
<DCCReference Include="..\sources\MVCFramework.Commons.pas"/>
<RcItem Include="DMVC.Expert.NewProject.ico">
<ResourceType>ICON</ResourceType>
<ResourceId>DMVCNewProjectIcon</ResourceId>

View File

@ -2,7 +2,7 @@
//
// LoggerPro
//
// Copyright (c) 2010-2018 Daniele Teti
// Copyright (c) 2010-2019 Daniele Teti
//
// https://github.com/danieleteti/loggerpro
//

View File

@ -0,0 +1,94 @@
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 3.x'}
{$LIBSUFFIX '102'}
{$RUNONLY}
{$IMPLICITBUILD ON}
requires
rtl,
inet,
dclcommon,
dcldb,
FireDAC,
IndyCore,
IndyProtocols,
FireDACIBDriver,
FireDACMySQLDriver,
loggerproRT;
contains
JsonDataObjects in '..\..\sources\JsonDataObjects.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 in '..\..\sources\MVCFramework.pas',
MVCFramework.Patches in '..\..\sources\MVCFramework.Patches.pas',
MVCFramework.RESTAdapter in '..\..\sources\MVCFramework.RESTAdapter.pas',
MVCFramework.RESTClient in '..\..\sources\MVCFramework.RESTClient.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.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.SQLGenerators.Firebird in '..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
MVCFramework.SQLGenerators.MySQL in '..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
MVCFramework.SysControllers in '..\..\sources\MVCFramework.SysControllers.pas',
MVCFramework.SystemJSONUtils in '..\..\sources\MVCFramework.SystemJSONUtils.pas',
MVCFramework.View.Cache in '..\..\sources\MVCFramework.View.Cache.pas';
end.

View File

@ -0,0 +1,598 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{96D17257-AF74-48CB-9893-7BCCB56A069D}</ProjectGuid>
<MainSource>dmvcframeworkRT.dpk</MainSource>
<ProjectVersion>18.5</ProjectVersion>
<FrameworkType>None</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Package</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
<Base_Android>true</Base_Android>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<GenDll>true</GenDll>
<GenPackage>true</GenPackage>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
<DCC_CBuilderOutput>All</DCC_CBuilderOutput>
<SanitizedProjectName>dmvcframeworkRT</SanitizedProjectName>
<RuntimeOnlyPackage>true</RuntimeOnlyPackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android)'!=''">
<DCC_CBuilderOutput>None</DCC_CBuilderOutput>
<EnabledSysJars>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-ads-7.0.0.dex.jar;google-play-services-analytics-7.0.0.dex.jar;google-play-services-base-7.0.0.dex.jar;google-play-services-gcm-7.0.0.dex.jar;google-play-services-identity-7.0.0.dex.jar;google-play-services-maps-7.0.0.dex.jar;google-play-services-panorama-7.0.0.dex.jar;google-play-services-plus-7.0.0.dex.jar;google-play-services-wallet-7.0.0.dex.jar</EnabledSysJars>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<Debugger_HostApplication>C:\DEV\dmscontainer_centrosoftware\bin\DMSContainerService.exe</Debugger_HostApplication>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_MapFile>3</DCC_MapFile>
<DCC_Description>DMVCFramework 3.x</DCC_Description>
<DllSuffix>102</DllSuffix>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="rtl.dcp"/>
<DCCReference Include="inet.dcp"/>
<DCCReference Include="dclcommon.dcp"/>
<DCCReference Include="dcldb.dcp"/>
<DCCReference Include="FireDAC.dcp"/>
<DCCReference Include="IndyCore.dcp"/>
<DCCReference Include="IndyProtocols.dcp"/>
<DCCReference Include="FireDACIBDriver.dcp"/>
<DCCReference Include="FireDACMySQLDriver.dcp"/>
<DCCReference Include="loggerproRT.dcp"/>
<DCCReference Include="..\..\sources\JsonDataObjects.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ActiveRecord.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ActiveRecordController.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ApplicationSession.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Cache.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Commons.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Console.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DataSet.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DuckTyping.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.FireDAC.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.HMAC.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JSONRPC.Client.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JSONRPC.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JWT.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Logger.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Analytics.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Authentication.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Authentication.RoleBasedAuthHandler.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Compression.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.CORS.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.JWT.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.SecurityHeaders.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.MultiMap.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Patches.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RESTAdapter.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RESTClient.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Router.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.Parser.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Rtti.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Abstract.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Commons.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Defaults.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Intf.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.JsonDataObjects.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Session.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.Firebird.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SysControllers.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SystemJSONUtils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.View.Cache.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Package</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">dmvcframeworkRT.dpk</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k250.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k250.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp250.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
<Platform Name="OSX64">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl\dmvcframeworkRT103.bpl" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>dmvcframeworkRT.bpl</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV21">
<Platform Name="Android">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug"/>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
</Deployment>
<Platforms>
<Platform value="Android">False</Platform>
<Platform value="Linux64">False</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -0,0 +1,94 @@
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 3.x'}
{$LIBSUFFIX '103'}
{$RUNONLY}
{$IMPLICITBUILD ON}
requires
rtl,
inet,
dclcommon,
dcldb,
FireDAC,
IndyCore,
IndyProtocols,
FireDACIBDriver,
FireDACMySQLDriver,
loggerproRT;
contains
JsonDataObjects in '..\..\sources\JsonDataObjects.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 in '..\..\sources\MVCFramework.pas',
MVCFramework.Patches in '..\..\sources\MVCFramework.Patches.pas',
MVCFramework.RESTAdapter in '..\..\sources\MVCFramework.RESTAdapter.pas',
MVCFramework.RESTClient in '..\..\sources\MVCFramework.RESTClient.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.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.SQLGenerators.Firebird in '..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
MVCFramework.SQLGenerators.MySQL in '..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
MVCFramework.SysControllers in '..\..\sources\MVCFramework.SysControllers.pas',
MVCFramework.SystemJSONUtils in '..\..\sources\MVCFramework.SystemJSONUtils.pas',
MVCFramework.View.Cache in '..\..\sources\MVCFramework.View.Cache.pas';
end.

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{96D17257-AF74-48CB-9893-7BCCB56A069D}</ProjectGuid>
<MainSource>dmvcframework.dpk</MainSource>
<MainSource>dmvcframeworkRT.dpk</MainSource>
<ProjectVersion>18.5</ProjectVersion>
<FrameworkType>None</FrameworkType>
<Base>True</Base>
@ -51,7 +51,8 @@
<GenPackage>true</GenPackage>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
<DCC_CBuilderOutput>All</DCC_CBuilderOutput>
<SanitizedProjectName>dmvcframework</SanitizedProjectName>
<SanitizedProjectName>dmvcframeworkRT</SanitizedProjectName>
<RuntimeOnlyPackage>true</RuntimeOnlyPackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android)'!=''">
<DCC_CBuilderOutput>None</DCC_CBuilderOutput>
@ -73,7 +74,12 @@
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<Debugger_HostApplication>C:\DEV\dmscontainer_centrosoftware\bin\DMSContainerService.exe</Debugger_HostApplication>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_MapFile>3</DCC_MapFile>
<DCC_Description>DMVCFramework 3.x</DCC_Description>
<DllSuffix>103</DllSuffix>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@ -94,52 +100,53 @@
<DCCReference Include="IndyProtocols.dcp"/>
<DCCReference Include="FireDACIBDriver.dcp"/>
<DCCReference Include="FireDACMySQLDriver.dcp"/>
<DCCReference Include="loggerpro.dcp"/>
<DCCReference Include="..\sources\JsonDataObjects.pas"/>
<DCCReference Include="..\sources\MVCFramework.ActiveRecord.pas"/>
<DCCReference Include="..\sources\MVCFramework.ActiveRecordController.pas"/>
<DCCReference Include="..\sources\MVCFramework.ApplicationSession.pas"/>
<DCCReference Include="..\sources\MVCFramework.Cache.pas"/>
<DCCReference Include="..\sources\MVCFramework.Commons.pas"/>
<DCCReference Include="..\sources\MVCFramework.Console.pas"/>
<DCCReference Include="..\sources\MVCFramework.DataSet.Utils.pas"/>
<DCCReference Include="..\sources\MVCFramework.DuckTyping.pas"/>
<DCCReference Include="..\sources\MVCFramework.FireDAC.Utils.pas"/>
<DCCReference Include="..\sources\MVCFramework.HMAC.pas"/>
<DCCReference Include="..\sources\MVCFramework.JSONRPC.Client.pas"/>
<DCCReference Include="..\sources\MVCFramework.JSONRPC.pas"/>
<DCCReference Include="..\sources\MVCFramework.JWT.pas"/>
<DCCReference Include="..\sources\MVCFramework.Logger.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.Analytics.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.Authentication.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.Authentication.RoleBasedAuthHandler.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.Compression.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.CORS.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.JWT.pas"/>
<DCCReference Include="..\sources\MVCFramework.Middleware.SecurityHeaders.pas"/>
<DCCReference Include="..\sources\MVCFramework.MultiMap.pas"/>
<DCCReference Include="..\sources\MVCFramework.pas"/>
<DCCReference Include="..\sources\MVCFramework.Patches.pas"/>
<DCCReference Include="..\sources\MVCFramework.RESTAdapter.pas"/>
<DCCReference Include="..\sources\MVCFramework.RESTClient.pas"/>
<DCCReference Include="..\sources\MVCFramework.Router.pas"/>
<DCCReference Include="..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
<DCCReference Include="..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
<DCCReference Include="..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
<DCCReference Include="..\sources\MVCFramework.RQL.Parser.pas"/>
<DCCReference Include="..\sources\MVCFramework.Rtti.Utils.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.Abstract.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.Commons.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.Defaults.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.Intf.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas"/>
<DCCReference Include="..\sources\MVCFramework.Serializer.JsonDataObjects.pas"/>
<DCCReference Include="..\sources\MVCFramework.Session.pas"/>
<DCCReference Include="..\sources\MVCFramework.SQLGenerators.Firebird.pas"/>
<DCCReference Include="..\sources\MVCFramework.SQLGenerators.MySQL.pas"/>
<DCCReference Include="..\sources\MVCFramework.SysControllers.pas"/>
<DCCReference Include="..\sources\MVCFramework.SystemJSONUtils.pas"/>
<DCCReference Include="..\sources\MVCFramework.View.Cache.pas"/>
<DCCReference Include="loggerproRT.dcp"/>
<DCCReference Include="..\..\sources\JsonDataObjects.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ActiveRecord.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ActiveRecordController.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.ApplicationSession.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Cache.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Commons.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Console.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DataSet.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DuckTyping.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.FireDAC.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.HMAC.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JSONRPC.Client.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JSONRPC.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.JWT.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Logger.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Analytics.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Authentication.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Authentication.RoleBasedAuthHandler.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Compression.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.CORS.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.JWT.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.SecurityHeaders.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.MultiMap.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Patches.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RESTAdapter.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RESTClient.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Router.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.Parser.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Rtti.Utils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Abstract.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Commons.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Defaults.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Intf.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.JsonDataObjects.CustomTypes.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.JsonDataObjects.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Session.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.Firebird.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SysControllers.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SystemJSONUtils.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.View.Cache.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
@ -158,8 +165,15 @@
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">dmvcframework.dpk</Source>
<Source Name="MainSource">dmvcframeworkRT.dpk</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="C:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl\LockBoxFMXDD250.bpl">TurboPack LockBox Delphi FMX designtime package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\DataExplorerDBXPluginEnt260.bpl">DBExpress Enterprise Data Explorer Integration</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="C:\Program Files (x86)\FastReports\LibD26\dclfrxtee26.bpl">FastReport 6.0 Tee Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
@ -187,9 +201,9 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl\dmvcframework.bpl" Configuration="Debug" Class="ProjectOutput">
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\20.0\Bpl\dmvcframeworkRT103.bpl" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>dmvcframework.bpl</RemoteName>
<RemoteName>dmvcframeworkRT.bpl</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>

View File

@ -1,89 +0,0 @@
package dmvcframework;
{$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}
{$IMPLICITBUILD ON}
requires
rtl,
inet,
dclcommon,
dcldb,
FireDAC,
IndyCore,
IndyProtocols,
FireDACIBDriver,
FireDACMySQLDriver,
loggerpro;
contains
JsonDataObjects in '..\sources\JsonDataObjects.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 in '..\sources\MVCFramework.pas',
MVCFramework.Patches in '..\sources\MVCFramework.Patches.pas',
MVCFramework.RESTAdapter in '..\sources\MVCFramework.RESTAdapter.pas',
MVCFramework.RESTClient in '..\sources\MVCFramework.RESTClient.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.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.SQLGenerators.Firebird in '..\sources\MVCFramework.SQLGenerators.Firebird.pas',
MVCFramework.SQLGenerators.MySQL in '..\sources\MVCFramework.SQLGenerators.MySQL.pas',
MVCFramework.SysControllers in '..\sources\MVCFramework.SysControllers.pas',
MVCFramework.SystemJSONUtils in '..\sources\MVCFramework.SystemJSONUtils.pas',
MVCFramework.View.Cache in '..\sources\MVCFramework.View.Cache.pas';
end.

View File

@ -0,0 +1,59 @@
# 3.0.0 breaking changes
- XE6 and previous versions are not more supported.
- ```RenderListAsProperty<T>``` has been removed from TMVCController. You can set such kind of specialized serializations in your custom base controller.
- ```RenderJSONArrayAsProperty``` has been removed from TMVCController. You can set such kind of specialized serializations in your custom base controller.
- ```Render``` has been removed from TMVCController (was deprecated).
- ```Render(TJSONValue)``` has been removed from TMVCController (use Render(TObject)).
- Trying to deserialize a ```TJSONNull``` the target instance will not be freed anymore (consistency with serialize).
- ```Context.Request.BodyAsJSONObject``` dosen't exist any more. Use BodyAs<T> or the following pattern to migrate:
```
JSON := TJSONObject.ParseJSONValue(Context.Request.Body) as TJSONObject;
try
if not Assigned(JSON) then
raise EMVCException.Create('Invalid JSON');
// do something here
finally
JSON.Free;
end;
```
- ```TMVCConfigKey``` moved to unit ```MVCFramework.Commons```.
- ```TMVCMimeType``` was renamed to ```TMVCMediaType```.
- ```TMVCController.Render;``` no parameter method do not exist anymore. If the return is a ResponseStream, use the ```RenderResponseStream;```.
- ```TMVCController.PushJSONToView;``` was renamed to ```PushToView```and Removed SystemJSON dependency, use the ToJSON method if necessary.
- There is no more a default view engine for Server Side Views (before 3.0 there was mustache).
- Mustache engine is no more the only view engine available. Now you can implement all the view engines you need (check the serversideviewsprimer).
- On Linux there is no built-in available view engine available. In other words, using only the built-in classes, you cannot use server side views on linux (dmustache is not compatible on linux).
- HTTP File Upload doesn't work on Linux because of a bug in Delphi 10.2 (https://quality.embarcadero.com/browse/RSP-17216).
- ```[MapperJSONNaming(TJSONNameCase.JSONNameLowerCase)]``` now must be changed in ```[MVCNameCase(ncLowerCase)]```
- ```[MapperJSONNaming(TJSONNameCase.JSONNameUpperCase)]``` now must be changed in ```[MVCNameCase(ncUpperCase)]```
## TRESTClient
Every reference to TJSON* has been removed from the TRESTClient public interface. To port the existing code, you have to include ```MVCFramework.RESTClient.SystemJSONUtils``` and change your code as following:
Before
```lMyJSONObject := Response.BodyAsJsonObject.Clone as TJSONObject;```
After
```delphi
lMyJSONObject := TSystemJSON.BodyAsJsonObject(Response) as TJSONObject;
try
//use the object
finally
lMyJSONObject.Free;
end;
```
The memory allocated for the TJSONValue descendant (e.g. TJSONObject, TJSONArray and so on) *is no more managed by the TRESTClient itself* but must be feed by the calling code.
- DelphiStompClient has been removed from the core. The following method is no more available in TMVCController.
```delphi
function GetNewStompClient(const AClientId: string = ''): IStompClient;
```
- ```TMVCConfigKey.ISAPIPath``` has been substituted with ```TMVCConfigKey.PathPrefix``` and now is applicated to all kind of projects (not only ISAPI);
- ```MapperSerializeAsString``` attribute is now ```MVCSerializeAsString```
- ```ContentCharset``` is no more available (everywhere). You have to properly set ContentType. To do that is available the function ```CreateContentType```.
- Removed ```LogEx``` and ```LogException```. Use ```Log.ErrorFmt``` instead.
- `PushObjectToView` has been deprecated. Use `ViewData` property;
- `PushDataSetToView` has been deprecated. Use `ViewDataSet` property;
- `ViewModels` has been renamed in `ViewModelList`;
- `ViewDataSets` has been renamed in `ViewDatasetList`;

View File

@ -0,0 +1,4 @@
# 3.1.0 (lithium) breaking changes
- JSON-RPC Client Classes has been changed. Now they are interfaces based.
- JSON-RPC Server: Only public instance methods can be invoked.

View File

@ -0,0 +1,53 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,379 @@
![DelphiMVCFramework Logo](docs/dmvcframework_logofacebook.png)
# DelphiMVCFramework 3.0.0-hydrogen is [here](https://github.com/danieleteti/delphimvcframework/releases/tag/v3.0.0-hydrogen)!
## DelphiMVCFramework Main Features
* Simple to use, check the ["Getting Started: 5 minutes guide"](https://danieleteti.gitbooks.io/delphimvcframework/content/chapter_getting_started.html) and you will be up and running in 5 minutes or less!
* [Project Roadmap](roadmap.md) is always public
* More than 40 samples to learn all the features and be proficient and productive
* RESTful (RMM Level 3) compliant
* JSON-RPC 2.0 Support
* Stable and solid, used by small/mid/big projects since 2010
* Fast, fast, fast!
* Support group at https://www.facebook.com/groups/delphimvcframework with more than 1400 active members
* Can be used in load balanced environment
* Wizard for the Delphi IDE. It makes DelphiMVCFramework even more simple to use!
* Optional session support
* JSON Web Token Support (JWT)
* Extendable using middlewares (simple hooks to handle request/response)
* Flexible yet simple to use, authorization/authentication framework based on industry standards.
* HTTP Basic Authentication
* JWT Authentication
* Custom Authentication
* CORS support
* Controllers inheritance! You can define your own base controller and inherith from it.
* Fancy URL with parameter mappings
* Specialied renders to generate text, HTML, JSON.
* Powerful and customizable mapper to serialize/deserialize data.
* Can be packaged as stand alone server, apache module (XE6 or better) and ISAPI dll
* Integrated RESTClient
* Works with XE7, XE8, Delphi 10 Seattle, Delphi 10.1 Berlin, Delphi 10.2 Tokyo
* Works on Linux (Delphi 10.2 Tokyo or better)
* Completely unit tested
* There is a sample for each functionality
* There is a complete set of trainings about it, but the samples are included in the project
* Server side generated pages using Mustache (https://mustache.github.io/) for Delphi (https://github.com/synopse/dmustache)
* Specific trainings are available (email to professionals@bittime.it for a date and a place)
* Messaging extension using ServerSentEvents
* Automatic documentation through /system/describeserver.info
* Driven by its huge community (Facebook group https://www.facebook.com/groups/delphimvcframework)
* Semantic Versioning
* Simple and [documented](docs/ITDevCON%202013%20-%20Introduction%20to%20DelphiMVCFramework.pdf)
* Check the [DMVCFramework Developer Guide](https://danieleteti.gitbooks.io/delphimvcframework/content/) (work in progress)
## What users says about DMVCFramework
>"DMVCFramework is a great framework. It's very intuitive, fast, easy to use, actually there is nothing more to ask for." -- Samir
>"Wow! To do that in J2EE it takes 2 days" -- a training participant after a 5 minutes demo.
>"I'm starting with the DMVCFramework and I'm finding it fantastic, congratulations for the project!" -- Rafael
>"I'm looking at DMVCFramework project in it works great - for my use case scenarios is much better than *'Similar commercial product'*." -- Luka
>"It's fantastic! Just define your entities and you are up and running in 5 minutes. Nothing comparable on the market." -- Marco
## What's New
### DelphiMVCFramework 3.1.0 lithium (currently in beta)
- New! Added `TMVCActiveRecord` framework (check sample `activerecord_showcase` and `activerecord_crud`)
- New! Added `TMVCActiveRecordController` (check sample `activerecord_crud`)
- Automatic permissions handling for `TMVCActiveRecordController` (check sample `activerecord_crud`)
- EntityProcessor for `TMVCActiveRecordController` (check sample `activerecord_crud`)
- `Config[TMVCConfigKey.FallbackResource]` is served only if request path is empty or `/`.
- New! Now the JSON-RPC executor provides methods to handle HTTP headers for JSON-RPC requests and notifications.
- `TDataSetHolder` is a new render that is able to render a dataset with a set of custom metadata (eg `count`,`page` etc). Check [issue #137](https://github.com/danieleteti/delphimvcframework/issues/137)
- `404` and `500` status code returns always a `text/plain` content-type
- Refactored ISAPI sample
- Speed improvement! Removed enhanced visibility for action methods. Now only public and published methods can be used as actions.
- `TMVCController.Create` is `virtual`! Now on your base controllers can be even more powerful!
- New! Added `MAX_REQUEST_SIZE` for limiting the size of the incoming HTTP requests. IDE Expert is updated too!
- New! Added method `TMVCJsonDataObjectsSerializer.ListToJsonArray`
- New! `TMVCResponse` for handle generic (non error) response
- New! `TMVCErrorResponse` for handle generic error response
- New! Added class `TMVCActiveRecordList` used in the manual `TMVCActiveRecord` programming
- New! Added `gzip` compression support in addition to `deflate` in `TCompressionMiddleware`
- FIX for [issue #143](https://github.com/danieleteti/delphimvcframework/issues/143)
- FIX for [issue #141](https://github.com/danieleteti/delphimvcframework/issues/141)
- Removed deprecated methods in `IRESTResponse`
- FIX misspelled header name in `IRESTResponse`
- New! Added `gzip` and `deflate` support in `TRestClient` when reading responses
- `TCompressionMiddleware` has been renamed in `TMVCCompressionMiddleware`
- New! `TMVCCompressionMiddleware` is added by IDE Expert by default
- Removed the old JSON serializer based on `System.JSON.pas', now the only available JSON serializer is based on [JsonDataObjects](https://github.com/ahausladen/JsonDataObjects) parser (Thank you Andreas Hausladen).
- Changed! Custom Types Serializer *must* be registered by media-type only, without charset definition (e.g. just `application/json` and not `application/json;charset=utf-8`)
- Changed! `IMVCTypeSerializer` is more powerful and simple to use!
- Sending wrongly formatted JSON now returns a more correctly `400 Bad Request` and not `500 Internal Server Error` as in the previous versions
- New! Support for Spring4d nullable types (check `samples\renders_spring4d_nullables`)
- New! `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even datamodules) through a JSON-RPC 2.0 interface!
- *Breaking Change!* The JSON RPC Client layer is now interface based.
## How to correctly get the source
It is not needed to download the git repository. Just download the [latest version as zip file](https://github.com/danieleteti/delphimvcframework/releases/tag/v3.0.0-hydrogen) and you are ok.
## Roadmap
DelphiMVCFramework roadmap is always updated as-soon-as the features planned are implemented. Check the roadmap [here](roadmap.md).
## Trainings, consultancy or custom development service
As you know, good support on open source software is a must for professional users.
If you need trainings, consultancy or custom developments on DelphiMVCFramework, send an email to *dmvcframework at bittime dot it*. Alternatively you can send a request using the [contacts forms](http://www.bittimeprofessionals.it/contatti) on [bittimeprofessionals website](http://www.bittimeprofessionals.it). bit Time Professionals is the company behind DelphiMVCFramework, al the main developers works there.
### Using mapping framework in Delphi Starter Edition
A lot of users ask about it, now is possible to use the mapper framework also in Delphi Started Edition. To enable the "StarterEditionMode" open ```sources\dmvcframework.inc``` and remove the dot (.) after the curly brace in the following line
```{.$DEFINE STARTEREDITION}```
become
```{$DEFINE STARTEREDITION}```
## Release Notes
**3.0.0 (hydrogen)**
- First release of the 3.0.0 version
**2.1.3 (lithium)**
- FIX https://github.com/danieleteti/delphimvcframework/issues/64
- Added unit tests to avoid regressions
**2.1.2 (helium)**
- FIX for Delphi versions who don't have ```TJSONBool``` (Delphi XE8 or older)
- Added new conditional define in dmvcframework.inc: JSONBOOL (defined for Delphi Seattle+)
**2.1.1 (hydrogen)**
- Updated the IDE Expert to show the current version of the framework
- FIX to the mapper about the datasets null values (needs to be checked in old Delphi versions)
- ADDED support for boolean values in datasets serialization
- ADDED unit tests about Mapper and dataset fields nullability
- The current version is available in constant ```DMVCFRAMEWORK_VERSION``` defined in ```MVCFramework.Commons.pas```
## Samples and documentation
DMVCFramework is provided with a lot of examples focused on specific functionality.
All samples are in [Samples](samples) folder.
Check the [DMVCFramework Developer Guide](https://danieleteti.gitbooks.io/delphimvcframework/content/) (work in progress).
# Getting Started
Below the is a basic sample of a DMVCFramework server wich can be deployed as standa-alone application, as an Apache module or as ISAPI dll. This flexibility is provided by the Delphi WebBroker framework (built-in in Delphi since Delphi 4).
The project containes an IDE Expert which make creating DMVCFramework project a breeze. However not all the Delphi version are supported, so here's the manual version (which is not complicated at all).
To create this server, you have to create a new ```Delphi Projects -> WebBroker -> WebServerApplication```. Then add the following changes to the webmodule.
```delphi
unit WebModuleUnit1;
interface
uses System.SysUtils, System.Classes, Web.HTTPApp, MVCFramework {this unit contains TMVCEngine class};
type
TWebModule1 = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
MVC: TMVCEngine;
public
{ Public declarations }
end;
var
WebModuleClass: TComponentClass = TWebModule1;
implementation
{$R *.dfm}
uses UsersControllerU; //this is the unit where is defined the controller
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
MVC := TMVCEngine.Create(Self);
MVC.Config[TMVCConfigKey.DocumentRoot] := 'public_html'; //if you need some static html, javascript, etc (optional)
MVC.AddController(TUsersController); //see next section to know how to create a controller
end;
procedure TWebModule1.WebModuleDestroy(Sender: TObject);
begin
MVC.Free;
end;
end.
```
Remember that the files inside the redist folder *must* be in the executable path or in the system path. If starting the server whithin the IDE doesn't works, try to run the executable outside the IDE and check the dependencies.
That's it! You have just created your first DelphiMVCFramework. Now you have to add a controller to respond to the http request.
## Sample Controller
Below a basic sample of a DMVCFramework controller with 2 action
```delphi
unit UsersControllerU;
interface
uses
MVCFramework;
type
[MVCPath('/users')]
TUsersController = class(TMVCController)
public
//The following action will be with a GET request like the following
//http://myserver.com/users/3
[MVCPath('/($id)')]
[MVCProduces('application/json')]
[MVCHTTPMethod([httpGET])]
[MVCDoc('Returns a user as a JSON object')]
procedure GetUser(id: Integer);
//The following action will be with a GET request like the following
//http://myserver.com/users
[MVCPath('/')]
[MVCProduces('application/json')]
[MVCHTTPMethod([httpGET])]
[MVCDoc('Returns the users list as a JSON Array of JSON Objects')]
procedure GetUsers;
//The following action will be with a PUT request like the following
//http://myserver.com/users/3
//and in the request body there should be a serialized TUser
[MVCPath('/($id)')]
[MVCProduce('application/json')]
[MVCHTTPMethod([httpPUT])]
[MVCDoc('Update a user')]
procedure UpdateUser(id: Integer);
//The following action will respond to a POST request like the following
//http://myserver.com/users
//and in the request body there should be the new user to create as json
[MVCPath]
[MVCProduce('application/json')]
[MVCHTTPMethod([httpPOST])]
[MVCDoc('Create a new user, returns the id of the new user')]
procedure CreateUser;
end;
implementation
uses
MyTransactionScript; //contains actual data access code
{ TUsersController }
procedure TUsersController.GetUsers;
var
Users: TObjectList<TUser>;
begin
Users := GetUsers;
Render(Users);
end;
procedure TUsersController.GetUser(id: Integer);
var
User: TUser;
begin
User := GetUserById(id);
Render(User);
end;
procedure TUsersController.UpdateUser(id: Integer);
var
User: TUser;
begin
User := Context.Request.BodyAs<TUser>;
UpdateUser(id, User);
Render(User);
end;
procedure TUsersController.CreateUser;
var
User: TUser;
begin
User := Context.Request.BodyAs<TUser>;
CreateUser(User);
Render(User);
end;
end.
```
Now you have a performant RESTful server wich respond to the following URLs:
- GET /users/($id) (eg. /users/1, /users/45 etc)
- PUT /users/($id) (eg. /users/1, /users/45 etc with the JSON data in the request body)
- POST /users (the JSON data must be in the request body)
### Quick Creation of DelphiMVCFramework Server
If you dont plan to deploy your DMVCFramework server behind a webserver (apache or IIS) you can also pack more than one listener application server into one single executable. In this case, the process is a bit different and involves the creation of a listener context. However, create a new server is a simple task:
```delphi
uses
MVCFramework.Server,
MVCFramework.Server.Impl;
var
LServerListener: IMVCListener;
begin
LServerListener := TMVCListener.Create(TMVCListenerProperties.New
.SetName('Listener1')
.SetPort(5000)
.SetMaxConnections(1024)
.SetWebModuleClass(YourServerWebModuleClass)
);
LServerListener.Start;
LServerListener.Stop;
end;
```
If you want to add a layer of security (in its WebModule you should add the security middleware):
```delphi
uses
MVCFramework.Server,
MVCFramework.Server.Impl,
MVCFramework.Middleware.Authentication;
procedure TTestWebModule.WebModuleCreate(Sender: TObject);
begin
FMVCEngine := TMVCEngine.Create(Self);
// Add Yours Controllers
FMVCEngine.AddController(TYourController);
// Add Security Middleware
FMVCEngine.AddMiddleware(TMVCBasicAuthenticationMiddleware.Create(
TMVCDefaultAuthenticationHandler.New
.SetOnAuthentication(
procedure(const AUserName, APassword: string;
AUserRoles: TList<string>; var IsValid: Boolean;
const ASessionData: TDictionary<String, String>)
begin
IsValid := AUserName.Equals('dmvc') and APassword.Equals('123');
end
)
));
end;
```
In stand alone mode you can work with a context that supports multiple listeners servers:
```delphi
uses
MVCFramework.Server,
MVCFramework.Server.Impl;
var
LServerListenerCtx: IMVCListenersContext;
begin
LServerListenerCtx := TMVCListenersContext.Create;
LServerListenerCtx.Add(TMVCListenerProperties.New
.SetName('Listener1')
.SetPort(6000)
.SetMaxConnections(1024)
.SetWebModuleClass(WebModuleClass1)
);
LServerListenerCtx.Add(TMVCListenerProperties.New
.SetName('Listener2')
.SetPort(7000)
.SetMaxConnections(1024)
.SetWebModuleClass(WebModuleClass2)
);
LServerListenerCtx.StartAll;
end;
```
### Links
Feel free to ask questions on the "Delphi MVC Framework" facebook group (https://www.facebook.com/groups/delphimvcframework).

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
colorama==0.4.1
invoke==1.2.0

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -12,6 +12,7 @@ object MainForm: TMainForm
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
DesignSize = (
635
299)

View File

@ -47,6 +47,7 @@ type
procedure btnSelectClick(Sender: TObject);
procedure btnValidationClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
procedure Log(const Value: string);
public
@ -60,7 +61,6 @@ implementation
{$R *.dfm}
uses
MVCFramework.ActiveRecord,
EntitiesU,
@ -142,14 +142,11 @@ begin
else
raise Exception.Create('Unknown backend for direct SQL execution');
lProc :=
procedure
lProc := procedure
var
lConn: TFDConnection;
lCustomer:
TCustomer;
I:
Integer;
lCustomer: TCustomer;
I: Integer;
begin
lConn := TFDConnection.Create(nil);
try
@ -174,17 +171,8 @@ begin
end;
end;
lTasks := [
TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
, TTask.Run(lProc)
];
lTasks := [TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc)];
TTask.WaitForAll(lTasks);
end;
@ -360,10 +348,12 @@ begin
ActiveRecordConnectionsRegistry.AddConnection('default', FDConnection1);
end;
procedure TMainForm.Log(
const
Value:
string);
procedure TMainForm.FormDestroy(Sender: TObject);
begin
ActiveRecordConnectionsRegistry.RemoveConnection('default');
end;
procedure TMainForm.Log(const Value: string);
begin
Memo1.Lines.Add(Value);
Memo1.Update;

View File

@ -9,7 +9,9 @@ uses
MVCFramework.RQL.AST2FirebirdSQL in '..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
MVCFramework.SQLGenerators.MySQL in '..\..\sources\MVCFramework.SQLGenerators.MySQL.pas',
MVCFramework.SQLGenerators.Firebird in '..\..\sources\MVCFramework.SQLGenerators.Firebird.pas',
MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas';
MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
MVCFramework.RQL.AST2InterbaseSQL in '..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas',
MVCFramework.RQL.AST2PostgreSQL in '..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas';
{$R *.res}

View File

@ -113,6 +113,8 @@
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.SQLGenerators.Firebird.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,602 @@
/*!
* Milligram v1.3.0
* https://milligram.github.io
*
* Copyright (c) 2017 CJ Patoilo
* Licensed under the MIT license
*/
*,
*:after,
*:before {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: 62.5%;
}
body {
color: #606c76;
font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
font-size: 1.6em;
font-weight: 300;
letter-spacing: .01em;
line-height: 1.6;
}
blockquote {
border-left: 0.3rem solid #d1d1d1;
margin-left: 0;
margin-right: 0;
padding: 1rem 1.5rem;
}
blockquote *:last-child {
margin-bottom: 0;
}
.button,
button,
input[type='button'],
input[type='reset'],
input[type='submit'] {
background-color: #9b4dca;
border: 0.1rem solid #9b4dca;
border-radius: .4rem;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 1.1rem;
font-weight: 700;
height: 3.8rem;
letter-spacing: .1rem;
line-height: 3.8rem;
padding: 0 3.0rem;
text-align: center;
text-decoration: none;
text-transform: uppercase;
white-space: nowrap;
}
.button:focus, .button:hover,
button:focus,
button:hover,
input[type='button']:focus,
input[type='button']:hover,
input[type='reset']:focus,
input[type='reset']:hover,
input[type='submit']:focus,
input[type='submit']:hover {
background-color: #606c76;
border-color: #606c76;
color: #fff;
outline: 0;
}
.button[disabled],
button[disabled],
input[type='button'][disabled],
input[type='reset'][disabled],
input[type='submit'][disabled] {
cursor: default;
opacity: .5;
}
.button[disabled]:focus, .button[disabled]:hover,
button[disabled]:focus,
button[disabled]:hover,
input[type='button'][disabled]:focus,
input[type='button'][disabled]:hover,
input[type='reset'][disabled]:focus,
input[type='reset'][disabled]:hover,
input[type='submit'][disabled]:focus,
input[type='submit'][disabled]:hover {
background-color: #9b4dca;
border-color: #9b4dca;
}
.button.button-outline,
button.button-outline,
input[type='button'].button-outline,
input[type='reset'].button-outline,
input[type='submit'].button-outline {
background-color: transparent;
color: #9b4dca;
}
.button.button-outline:focus, .button.button-outline:hover,
button.button-outline:focus,
button.button-outline:hover,
input[type='button'].button-outline:focus,
input[type='button'].button-outline:hover,
input[type='reset'].button-outline:focus,
input[type='reset'].button-outline:hover,
input[type='submit'].button-outline:focus,
input[type='submit'].button-outline:hover {
background-color: transparent;
border-color: #606c76;
color: #606c76;
}
.button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover,
button.button-outline[disabled]:focus,
button.button-outline[disabled]:hover,
input[type='button'].button-outline[disabled]:focus,
input[type='button'].button-outline[disabled]:hover,
input[type='reset'].button-outline[disabled]:focus,
input[type='reset'].button-outline[disabled]:hover,
input[type='submit'].button-outline[disabled]:focus,
input[type='submit'].button-outline[disabled]:hover {
border-color: inherit;
color: #9b4dca;
}
.button.button-clear,
button.button-clear,
input[type='button'].button-clear,
input[type='reset'].button-clear,
input[type='submit'].button-clear {
background-color: transparent;
border-color: transparent;
color: #9b4dca;
}
.button.button-clear:focus, .button.button-clear:hover,
button.button-clear:focus,
button.button-clear:hover,
input[type='button'].button-clear:focus,
input[type='button'].button-clear:hover,
input[type='reset'].button-clear:focus,
input[type='reset'].button-clear:hover,
input[type='submit'].button-clear:focus,
input[type='submit'].button-clear:hover {
background-color: transparent;
border-color: transparent;
color: #606c76;
}
.button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover,
button.button-clear[disabled]:focus,
button.button-clear[disabled]:hover,
input[type='button'].button-clear[disabled]:focus,
input[type='button'].button-clear[disabled]:hover,
input[type='reset'].button-clear[disabled]:focus,
input[type='reset'].button-clear[disabled]:hover,
input[type='submit'].button-clear[disabled]:focus,
input[type='submit'].button-clear[disabled]:hover {
color: #9b4dca;
}
code {
background: #f4f5f6;
border-radius: .4rem;
font-size: 86%;
margin: 0 .2rem;
padding: .2rem .5rem;
white-space: nowrap;
}
pre {
background: #f4f5f6;
border-left: 0.3rem solid #9b4dca;
overflow-y: hidden;
}
pre > code {
border-radius: 0;
display: block;
padding: 1rem 1.5rem;
white-space: pre;
}
hr {
border: 0;
border-top: 0.1rem solid #f4f5f6;
margin: 3.0rem 0;
}
input[type='email'],
input[type='number'],
input[type='password'],
input[type='search'],
input[type='tel'],
input[type='text'],
input[type='url'],
textarea,
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: transparent;
border: 0.1rem solid #d1d1d1;
border-radius: .4rem;
box-shadow: none;
box-sizing: inherit;
height: 3.8rem;
padding: .6rem 1.0rem;
width: 100%;
}
input[type='email']:focus,
input[type='number']:focus,
input[type='password']:focus,
input[type='search']:focus,
input[type='tel']:focus,
input[type='text']:focus,
input[type='url']:focus,
textarea:focus,
select:focus {
border-color: #9b4dca;
outline: 0;
}
select {
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#d1d1d1" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>') center right no-repeat;
padding-right: 3.0rem;
}
select:focus {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#9b4dca" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>');
}
textarea {
min-height: 6.5rem;
}
label,
legend {
display: block;
font-size: 1.6rem;
font-weight: 700;
margin-bottom: .5rem;
}
fieldset {
border-width: 0;
padding: 0;
}
input[type='checkbox'],
input[type='radio'] {
display: inline;
}
.label-inline {
display: inline-block;
font-weight: normal;
margin-left: .5rem;
}
.container {
margin: 0 auto;
max-width: 112.0rem;
padding: 0 2.0rem;
position: relative;
width: 100%;
}
.row {
display: flex;
flex-direction: column;
padding: 0;
width: 100%;
}
.row.row-no-padding {
padding: 0;
}
.row.row-no-padding > .column {
padding: 0;
}
.row.row-wrap {
flex-wrap: wrap;
}
.row.row-top {
align-items: flex-start;
}
.row.row-bottom {
align-items: flex-end;
}
.row.row-center {
align-items: center;
}
.row.row-stretch {
align-items: stretch;
}
.row.row-baseline {
align-items: baseline;
}
.row .column {
display: block;
flex: 1 1 auto;
margin-left: 0;
max-width: 100%;
width: 100%;
}
.row .column.column-offset-10 {
margin-left: 10%;
}
.row .column.column-offset-20 {
margin-left: 20%;
}
.row .column.column-offset-25 {
margin-left: 25%;
}
.row .column.column-offset-33, .row .column.column-offset-34 {
margin-left: 33.3333%;
}
.row .column.column-offset-50 {
margin-left: 50%;
}
.row .column.column-offset-66, .row .column.column-offset-67 {
margin-left: 66.6666%;
}
.row .column.column-offset-75 {
margin-left: 75%;
}
.row .column.column-offset-80 {
margin-left: 80%;
}
.row .column.column-offset-90 {
margin-left: 90%;
}
.row .column.column-10 {
flex: 0 0 10%;
max-width: 10%;
}
.row .column.column-20 {
flex: 0 0 20%;
max-width: 20%;
}
.row .column.column-25 {
flex: 0 0 25%;
max-width: 25%;
}
.row .column.column-33, .row .column.column-34 {
flex: 0 0 33.3333%;
max-width: 33.3333%;
}
.row .column.column-40 {
flex: 0 0 40%;
max-width: 40%;
}
.row .column.column-50 {
flex: 0 0 50%;
max-width: 50%;
}
.row .column.column-60 {
flex: 0 0 60%;
max-width: 60%;
}
.row .column.column-66, .row .column.column-67 {
flex: 0 0 66.6666%;
max-width: 66.6666%;
}
.row .column.column-75 {
flex: 0 0 75%;
max-width: 75%;
}
.row .column.column-80 {
flex: 0 0 80%;
max-width: 80%;
}
.row .column.column-90 {
flex: 0 0 90%;
max-width: 90%;
}
.row .column .column-top {
align-self: flex-start;
}
.row .column .column-bottom {
align-self: flex-end;
}
.row .column .column-center {
-ms-grid-row-align: center;
align-self: center;
}
@media (min-width: 40rem) {
.row {
flex-direction: row;
margin-left: -1.0rem;
width: calc(100% + 2.0rem);
}
.row .column {
margin-bottom: inherit;
padding: 0 1.0rem;
}
}
a {
color: #9b4dca;
text-decoration: none;
}
a:focus, a:hover {
color: #606c76;
}
dl,
ol,
ul {
list-style: none;
margin-top: 0;
padding-left: 0;
}
dl dl,
dl ol,
dl ul,
ol dl,
ol ol,
ol ul,
ul dl,
ul ol,
ul ul {
font-size: 90%;
margin: 1.5rem 0 1.5rem 3.0rem;
}
ol {
list-style: decimal inside;
}
ul {
list-style: circle inside;
}
.button,
button,
dd,
dt,
li {
margin-bottom: 1.0rem;
}
fieldset,
input,
select,
textarea {
margin-bottom: 1.5rem;
}
blockquote,
dl,
figure,
form,
ol,
p,
pre,
table,
ul {
margin-bottom: 2.5rem;
}
table {
border-spacing: 0;
width: 100%;
}
td,
th {
border-bottom: 0.1rem solid #e1e1e1;
padding: 1.2rem 1.5rem;
text-align: left;
}
td:first-child,
th:first-child {
padding-left: 0;
}
td:last-child,
th:last-child {
padding-right: 0;
}
b,
strong {
font-weight: bold;
}
p {
margin-top: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 300;
letter-spacing: -.1rem;
margin-bottom: 2.0rem;
margin-top: 0;
}
h1 {
font-size: 4.6rem;
line-height: 1.2;
}
h2 {
font-size: 3.6rem;
line-height: 1.25;
}
h3 {
font-size: 2.8rem;
line-height: 1.3;
}
h4 {
font-size: 2.2rem;
letter-spacing: -.08rem;
line-height: 1.35;
}
h5 {
font-size: 1.8rem;
letter-spacing: -.05rem;
line-height: 1.5;
}
h6 {
font-size: 1.6rem;
letter-spacing: 0;
line-height: 1.4;
}
img {
max-width: 100%;
}
.clearfix:after {
clear: both;
content: ' ';
display: table;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
/*# sourceMappingURL=milligram.css.map */

View File

@ -0,0 +1,107 @@
.header {
padding-top: 5px;
}
#wineList {
overflow-y: scroll;
height: 80%;
}
.leftArea {
position: absolute;
left: 10px;
top: 70px;
bottom: 20px;
width: 260px;
border:solid 1px #CCCCCC;
/*overflow-y: scroll;*/
}
.mainArea {
position: absolute;
top: 70px;
bottom: 20px;
left:300px;
/*overflow-y: scroll;*/
width:300px;
}
.rightArea {
position: absolute;
top: 70px;
bottom: 20px;
left:650px;
/*overflow-y: scroll;*/
width:280px;
}
ul {
list-style-type: none;
padding-left: 0px;
margin-top: 0px;
}
li a {
text-decoration:none;
display: block;
color: #000000;
border-bottom:solid 1px #CCCCCC;
padding: 8px;
}
li a:hover {
background-color: #4B0A1E;
color: #BA8A92;
}
input, textarea {
border:1px solid #ccc;
min-height:30px;
outline: none;
}
.mainArea input {
margin-bottom:15px;
margin-top:5px;
width:280px;
}
textarea {
margin-bottom:15px;
margin-top:5px;
height: 200px;
width:250px;
}
label {
display:block;
}
button {
padding:6px;
}
#searchKey {
width:160px;
}
.footer {
position:fixed;
left:0px;
bottom:0px;
height:30px;
width:100%;
background:#999;
}
.textcenter {
text-align: center;
}
.padding02 {
padding: 2px;
}

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Cellar</title>
<link rel="stylesheet" href="css/milligram.css" />
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<div class="header">
<input type="text" id="searchKey" />
<button class="button" id="btnSearch">Search</button>
<button class="button" id="btnAdd">New Wine</button>
</div>
<div class="leftArea">
<ul id="wineList"></ul>
</div>
<form id="wineForm">
<div class="mainArea">
<label>Id:</label>
<input id="wineId" name="id" type="text" style="width: 50px" disabled />
<label>Name:</label>
<input type="text" id="name" name="name" required>
<label>Grapes:</label>
<input type="text" id="grapes" name="grapes" />
<label>Country:</label>
<input type="text" id="country" name="country" />
<label>Region:</label>
<input type="text" id="region" name="region" />
<label>Year:</label>
<select id="year" name="year">
<option value=""></option>
</select>
<div class="padding02">
<button class="button" id="btnSave">Save</button>
<button class="button" id="btnDelete">Delete</button>
</div>
</div>
<div class="rightArea">
<img id="pic" height="300" />
<label>Notes:</label>
<textarea id="description" name="description"></textarea>
</div>
</form>
<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/main.js"></script>
<div class="footer textcenter padding02">The client code of this demo is slightly based on
<a target="_blank" href="http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/">"RESTful services with jQuery, PHP and the Slim Framework"</a>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,203 @@
// The root URL for the RESTful services
var rootURL = "/dmvc/api/wines";
var currentWine;
$(document).ready(function(){
//pupulate years combo
for (i = new Date().getFullYear(); i > 1940; i--)
{
$('#year').append($('<option />').val(i).html(i));
}
// Retrieve wine list when application starts
findAll();
// Nothing to delete in initial application state
$('#btnDelete').hide();
// Register listeners
$('#btnSearch').click(function() {
search($('#searchKey').val());
return false;
});
// Trigger search when pressing 'Return' on search key input field
$('#searchKey').keypress(function(e){
if(e.which == 13) {
search($('#searchKey').val());
e.preventDefault();
return false;
}
});
$('#btnAdd').click(function() {
newWine();
return false;
});
$('#btnSave').click(function() {
if ($('#wineId').val() == '')
{
addWine();
}
else
updateWine();
return false;
});
$('#btnDelete').click(function() {
deleteWine();
return false;
});
$('#wineList a').live('click', function() {
findById($(this).data('identity'));
});
// Replace broken images with generic wine bottle
$("img").error(function(){
$(this).attr("src", "pics/generic.jpg");
});
});
function search(searchKey) {
if (searchKey == '')
findAll();
else
findByName(searchKey);
}
function newWine() {
$('#btnDelete').hide();
currentWine = {};
renderDetails(currentWine); // Display empty form
}
function findAll() {
console.log('findAll');
$.ajax({
type: 'GET',
url: rootURL,
dataType: "json", // data type of response
success: renderList
});
}
function findByName(searchKey) {
console.log('findByName: ' + searchKey);
$.ajax({
type: 'GET',
url: rootURL + '/search/' + searchKey,
dataType: "json",
success: renderList
});
}
function findById(id) {
console.log('findById: ' + id);
$.ajax({
type: 'GET',
url: rootURL + '/' + id,
dataType: "json",
success: function(data){
$('#btnDelete').show();
console.log('findById success: ' + data.name);
currentWine = data;
renderDetails(currentWine);
}
});
}
function addWine() {
console.log('addWine');
$.ajax({
type: 'POST',
contentType: 'application/json',
url: rootURL,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('Wine created successfully');
$('#btnDelete').show();
$('#wineId').val(data.id);
findById(data.id);
},
error: function(jqXHR, textStatus, errorThrown){
alert('addWine error: ' + textStatus);
}
});
}
function updateWine() {
console.log('updateWine');
$.ajax({
type: 'PUT',
contentType: 'application/json',
url: rootURL + '/' + $('#wineId').val(),
dataType: "json",
data: formToJSON(),
processData: false,
success: function(data, textStatus, jqXHR){
debugger;
alert('Wine updated successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('updateWine error: ' + textStatus);
}
});
}
function deleteWine() {
console.log('deleteWine');
$.ajax({
type: 'DELETE',
url: rootURL + '/' + $('#wineId').val(),
success: function(data, textStatus, jqXHR){
alert('Wine deleted successfully');
findAll();
},
error: function(jqXHR, textStatus, errorThrown){
alert('deleteWine error');
}
});
}
function renderList(data) {
// JAX-RS serializes an empty list as null, and a 'collection of one' as an object (not an 'array of one')
//var list = data == null ? [] : (data.wine instanceof Array ? data.wine : [data.wine]);
//debugger;
var list = data;
$('#wineList li').remove();
$.each(list, function(index, wine) {
$('#wineList').append('<li><a href="#" data-identity="' + wine.id + '">'+wine.name+'</a></li>');
});
}
function renderDetails(wine) {
$('#wineId').val(wine.id);
$('#name').val(wine.name);
$('#grapes').val(wine.grapes);
$('#country').val(wine.country);
$('#region').val(wine.region);
$('#year').val(wine.year);
$('#pic').attr('src', 'pics/' + wine.picture);
$('#description').val(wine.description);
}
// Helper function to serialize all the form fields into a JSON string
function formToJSON() {
return JSON.stringify({
"id": $('#wineId').val(),
"name": $('#name').val(),
"grapes": $('#grapes').val(),
"country": $('#country').val(),
"region": $('#region').val(),
"year": $('#year').val(),
"picture": currentWine.picture,
"description": $('#description').val()
});
}

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

Binary file not shown.

View File

@ -98,217 +98,145 @@ uses
{$R *.dfm}
procedure TForm10.btnAddDayClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getnextmonday';
lReq.RequestID := Random(1000);
lReq.Params.Add(dtNextMonday.Date);
lResp := FExecutor.ExecuteRequest(lReq);
try
dtNextMonday.Date := ISOTimeStampToDateTime(lResp.Result.AsString);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'getnextmonday';
lReq.RequestID := Random(1000);
lReq.Params.Add(dtNextMonday.Date);
lResp := FExecutor.ExecuteRequest(lReq);
dtNextMonday.Date := ISOTimeStampToDateTime(lResp.Result.AsString);
end;
procedure TForm10.btnGetUserClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
lJSON: TJsonObject;
begin
lbPerson.Clear;
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getuser';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtUserName.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
lReq.Method := 'getuser';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtUserName.Text);
lResp := FExecutor.ExecuteRequest(lReq);
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonObject;
lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
finally
lResp.Free;
end;
finally
lReq.Free;
end;
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonObject;
lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
end;
procedure TForm10.btnInvalid1Click(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'invalidmethod1';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage(lResp.Error.ErrMessage);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'invalidmethod1';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage(lResp.Error.ErrMessage);
end;
procedure TForm10.btnInvalid2Click(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'invalidmethod2';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage(lResp.Error.ErrMessage);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'invalidmethod2';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage(lResp.Error.ErrMessage);
end;
procedure TForm10.btnInvalidMethodClick(Sender: TObject);
var
lNotification: TJSONRPCNotification;
lNotification: IJSONRPCNotification;
begin
lNotification := TJSONRPCNotification.Create;
try
lNotification.Method := 'notexists';
FExecutor.ExecuteNotification(lNotification);
finally
lNotification.Free;
end;
lNotification.Method := 'notexists';
FExecutor.ExecuteNotification(lNotification);
end;
procedure TForm10.btnNotificationClick(Sender: TObject);
var
lNotification: TJSONRPCNotification;
lNotification: IJSONRPCNotification;
begin
lNotification := TJSONRPCNotification.Create;
try
lNotification.Method := 'dosomething';
FExecutor.ExecuteNotification(lNotification);
finally
lNotification.Free;
end;
lNotification.Method := 'dosomething';
FExecutor.ExecuteNotification(lNotification);
end;
procedure TForm10.btnReverseStringClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'reversestring';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtReverseString.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
edtReversedString.Text := lResp.Result.AsString;
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'reversestring';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtReverseString.Text);
lResp := FExecutor.ExecuteRequest(lReq);
edtReversedString.Text := lResp.Result.AsString;
end;
procedure TForm10.btnSaveClick(Sender: TObject);
var
lPerson: TPerson;
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'saveperson';
lReq.RequestID := Random(1000);
lPerson := TPerson.Create;
lReq.Params.Add(lPerson);
lPerson.FirstName := edtFirstName.Text;
lPerson.LastName := edtLastName.Text;
lPerson.Married := chkMarried.Checked;
lPerson.DOB := dtDOB.Date;
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage('Person saved with ID = ' + lResp.Result.AsInteger.ToString);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'saveperson';
lReq.RequestID := Random(1000);
lPerson := TPerson.Create;
lReq.Params.Add(lPerson, TJSONRPCParamDataType.pdtObject);
lPerson.FirstName := edtFirstName.Text;
lPerson.LastName := edtLastName.Text;
lPerson.Married := chkMarried.Checked;
lPerson.DOB := dtDOB.Date;
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage('Person saved with ID = ' + lResp.Result.AsInteger.ToString);
end;
procedure TForm10.btnSubstractClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.Add(StrToInt(edtValue1.Text));
lReq.Params.Add(StrToInt(edtValue2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
try
edtResult.Text := lResp.Result.AsInteger.ToString;
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.Add(StrToInt(edtValue1.Text));
lReq.Params.Add(StrToInt(edtValue2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
edtResult.Text := lResp.Result.AsInteger.ToString;
end;
procedure TForm10.edtGetCustomersClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
FDMemTable1.Active := False;
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getcustomers';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtFilter.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
FDMemTable1.Active := True;
FDMemTable1.LoadFromTValue(lResp.Result);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'getcustomers';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtFilter.Text);
lResp := FExecutor.ExecuteRequest(lReq);
FDMemTable1.Active := True;
FDMemTable1.LoadFromTValue(lResp.Result);
end;
procedure TForm10.FormCreate(Sender: TObject);

View File

@ -34,21 +34,21 @@ object MainForm: TMainForm
object edtValue1: TEdit
Left = 17
Top = 32
Width = 70
Width = 32
Height = 21
TabOrder = 0
Text = '42'
end
object edtValue2: TEdit
Left = 93
Left = 55
Top = 32
Width = 70
Width = 26
Height = 21
TabOrder = 1
Text = '10'
end
object btnSubstract: TButton
Left = 169
Left = 87
Top = 30
Width = 100
Height = 25
@ -57,9 +57,9 @@ object MainForm: TMainForm
OnClick = btnSubstractClick
end
object edtResult: TEdit
Left = 273
Left = 193
Top = 32
Width = 70
Width = 27
Height = 21
ReadOnly = True
TabOrder = 3
@ -67,31 +67,31 @@ object MainForm: TMainForm
object edtReverseString: TEdit
Left = 17
Top = 80
Width = 144
Width = 88
Height = 21
TabOrder = 4
Text = 'Daniele Teti'
end
object btnReverseString: TButton
Left = 167
Left = 111
Top = 78
Width = 100
Width = 109
Height = 25
Caption = 'Reverse String'
TabOrder = 5
OnClick = btnReverseStringClick
end
object edtReversedString: TEdit
Left = 273
Left = 320
Top = 80
Width = 178
Width = 131
Height = 21
ReadOnly = True
TabOrder = 6
end
object dtNextMonday: TDateTimePicker
Left = 564
Top = 16
Left = 253
Top = 32
Width = 102
Height = 21
Date = 43018.000000000000000000
@ -99,9 +99,9 @@ object MainForm: TMainForm
TabOrder = 7
end
object btnAddDay: TButton
Left = 672
Top = 14
Width = 128
Left = 361
Top = 30
Width = 104
Height = 25
Caption = 'Get Next Monday'
TabOrder = 8
@ -171,6 +171,23 @@ object MainForm: TMainForm
WordWrap = True
OnClick = btnInvalidMethodClick
end
object CheckBox1: TCheckBox
Left = 226
Top = 82
Width = 88
Height = 17
Caption = 'As Uppercase'
TabOrder = 13
end
object btnDates: TButton
Left = 635
Top = 30
Width = 165
Height = 25
Caption = 'PlayWithDates'
TabOrder = 14
OnClick = btnDatesClick
end
end
object GroupBox2: TGroupBox
Left = 3

View File

@ -73,6 +73,8 @@ type
edtSearchText: TEdit;
btnSearch: TButton;
ListBox1: TListBox;
CheckBox1: TCheckBox;
btnDates: TButton;
procedure btnSubstractClick(Sender: TObject);
procedure btnReverseStringClick(Sender: TObject);
procedure edtGetCustomersClick(Sender: TObject);
@ -85,6 +87,7 @@ type
procedure btnNotificationClick(Sender: TObject);
procedure btnInvalidMethodClick(Sender: TObject);
procedure btnSearchClick(Sender: TObject);
procedure btnDatesClick(Sender: TObject);
private
FExecutor: IMVCJSONRPCExecutor;
FExecutor2: IMVCJSONRPCExecutor;
@ -103,260 +106,190 @@ uses
JsonDataObjects,
MVCFramework.Serializer.Commons,
MVCFramework.DataSet.Utils,
BusinessObjectsU;
BusinessObjectsU, System.Rtti;
{$R *.dfm}
procedure TMainForm.btnAddDayClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getnextmonday';
lReq.RequestID := Random(1000);
lReq.Params.Add(dtNextMonday.Date);
lResp := FExecutor.ExecuteRequest(lReq);
try
dtNextMonday.Date := ISOTimeStampToDateTime(lResp.Result.AsString);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'getnextmonday';
lReq.RequestID := Random(1000);
lReq.Params.Add(dtNextMonday.Date);
lResp := FExecutor.ExecuteRequest(lReq);
dtNextMonday.Date := ISOTimeStampToDateTime(lResp.Result.AsString);
end;
procedure TMainForm.btnDatesClick(Sender: TObject);
var
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create(1234, 'playwithdatesandtimes');
lReq.Params.Add(1234.5678, pdtFloat);
lReq.Params.Add(Time(), pdtTime);
lReq.Params.Add(Date(), pdtDate);
lReq.Params.Add(Now(), pdtDateTime);
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage(DateTimeToStr(lResp.Result.AsType<TDateTime>));
end;
procedure TMainForm.btnGetUserClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
lJSON: TJsonObject;
begin
lbPerson.Clear;
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getuser';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtUserName.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
lReq.Method := 'getuser';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtUserName.Text);
lResp := FExecutor.ExecuteRequest(lReq);
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonObject;
lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
finally
lResp.Free;
end;
finally
lReq.Free;
end;
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonObject;
lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
end;
procedure TMainForm.btnInvalid1Click(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'invalidmethod1';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage(lResp.Error.ErrMessage);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'invalidmethod1';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage(lResp.Error.ErrMessage);
end;
procedure TMainForm.btnInvalid2Click(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'invalidmethod2';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage(lResp.Error.ErrMessage);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'invalidmethod2';
lReq.Params.Add(1);
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage(lResp.Error.ErrMessage);
end;
procedure TMainForm.btnInvalidMethodClick(Sender: TObject);
var
lNotification: TJSONRPCNotification;
lNotification: IJSONRPCNotification;
begin
lNotification := TJSONRPCNotification.Create;
try
lNotification.Method := 'notexists';
FExecutor.ExecuteNotification(lNotification);
finally
lNotification.Free;
end;
lNotification.Method := 'notexists';
FExecutor.ExecuteNotification(lNotification);
end;
procedure TMainForm.btnNotificationClick(Sender: TObject);
var
lNotification: TJSONRPCNotification;
lNotification: IJSONRPCNotification;
begin
lNotification := TJSONRPCNotification.Create;
try
lNotification.Method := 'dosomething';
FExecutor.ExecuteNotification(lNotification);
finally
lNotification.Free;
end;
lNotification.Method := 'dosomething';
FExecutor.ExecuteNotification(lNotification);
end;
procedure TMainForm.btnReverseStringClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'reversestring';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtReverseString.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
edtReversedString.Text := lResp.Result.AsString;
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'reversestring';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtReverseString.Text);
lReq.Params.Add(CheckBox1.Checked);
lResp := FExecutor.ExecuteRequest(lReq);
edtReversedString.Text := lResp.Result.AsString;
end;
procedure TMainForm.btnSaveClick(Sender: TObject);
var
lPerson: TPerson;
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'saveperson';
lReq.RequestID := Random(1000);
lPerson := TPerson.Create;
lReq.Params.Add(lPerson);
lPerson.FirstName := edtFirstName.Text;
lPerson.LastName := edtLastName.Text;
lPerson.Married := chkMarried.Checked;
lPerson.DOB := dtDOB.Date;
lResp := FExecutor.ExecuteRequest(lReq);
try
ShowMessage('Person saved with ID = ' + lResp.Result.AsInteger.ToString);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'saveperson';
lReq.RequestID := Random(1000);
lPerson := TPerson.Create;
lReq.Params.Add(lPerson, pdtObject);
lPerson.FirstName := edtFirstName.Text;
lPerson.LastName := edtLastName.Text;
lPerson.Married := chkMarried.Checked;
lPerson.DOB := dtDOB.Date;
lResp := FExecutor.ExecuteRequest(lReq);
ShowMessage('Person saved with ID = ' + lResp.Result.AsInteger.ToString);
end;
procedure TMainForm.btnSearchClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
lJSON: TJsonArray;
I: Integer;
begin
lbPerson.Clear;
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'searchproducts';
lReq.RequestID := 1234;
lReq.Params.Add(edtSearchText.Text);
lResp := FExecutor2.ExecuteRequest(lReq);
try
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
lReq.Method := 'searchproducts';
lReq.RequestID := 1234;
lReq.Params.Add(edtSearchText.Text);
lResp := FExecutor2.ExecuteRequest(lReq);
if Assigned(lResp.Error) then
raise Exception.Create(lResp.Error.ErrMessage);
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonArray;
for I := 0 to lJSON.Count - 1 do
begin
ListBox1.Items.Add(lJSON[I].ObjectValue.ToJSON());
end;
// lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
// lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
// lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
// lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
finally
lResp.Free;
end;
finally
lReq.Free;
// Remember that TObject descendants (but TDataset, TJDOJSONObject and TJDOJSONArray)
// are serialized as JSON objects
lJSON := lResp.Result.AsObject as TJsonArray;
for I := 0 to lJSON.Count - 1 do
begin
ListBox1.Items.Add(lJSON[I].ObjectValue.ToJSON());
end;
// lbPerson.Items.Add('First Name:'.PadRight(15) + lJSON.S['firstname']);
// lbPerson.Items.Add('Last Name:'.PadRight(15) + lJSON.S['lastname']);
// lbPerson.Items.Add('Married:'.PadRight(15) + lJSON.B['married'].ToString(TUseBoolStrs.True));
// lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
end;
procedure TMainForm.btnSubstractClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.Add(StrToInt(edtValue1.Text));
lReq.Params.Add(StrToInt(edtValue2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
try
edtResult.Text := lResp.Result.AsInteger.ToString;
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq.Method := 'subtract';
lReq.RequestID := Random(1000);
lReq.Params.Add(StrToInt(edtValue1.Text));
lReq.Params.Add(StrToInt(edtValue2.Text));
lResp := FExecutor.ExecuteRequest(lReq);
edtResult.Text := lResp.Result.AsInteger.ToString;
end;
procedure TMainForm.edtGetCustomersClick(Sender: TObject);
var
lReq: TJSONRPCRequest;
lResp: TJSONRPCResponse;
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
begin
FDMemTable1.Active := False;
lReq := TJSONRPCRequest.Create;
try
lReq.Method := 'getcustomers';
lReq.RequestID := Random(1000);
lReq.Params.Add(edtFilter.Text);
lResp := FExecutor.ExecuteRequest(lReq);
try
FDMemTable1.Active := True;
FDMemTable1.LoadFromTValue(lResp.Result);
finally
lResp.Free;
end;
finally
lReq.Free;
end;
lReq := TJSONRPCRequest.Create(Random(1000), 'getcustomers');
lReq.Params.Add(edtFilter.Text);
lResp := FExecutor.ExecuteRequest(lReq);
FDMemTable1.Active := True;
FDMemTable1.LoadFromTValue(lResp.Result);
end;
procedure TMainForm.FormCreate(Sender: TObject);

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
@ -51,8 +51,9 @@ type
function GetPeopleDataset: TFDMemTable;
public
function Subtract(aValue1, aValue2: Integer): Integer;
function ReverseString(aString: string): string;
function ReverseString(const aString: string; const aUpperCase: Boolean): string;
function GetNextMonday(const aDate: TDate): TDate;
function PlayWithDatesAndTimes(const aJustAFloat: Double; const aTime: TTime; const aDate: TDate; const aDateAndTime: TDateTime): TDateTime;
function GetCustomers(aString: string): TDataset;
function GetMulti: TMultiDataset;
function GetStringDictionary: TMVCStringDictionary;
@ -200,9 +201,16 @@ begin
// do nothing
end;
function TMyObject.ReverseString(aString: string): string;
function TMyObject.PlayWithDatesAndTimes(const aJustAFloat: Double; const aTime: TTime; const aDate: TDate; const aDateAndTime: TDateTime): TDateTime;
begin
Result := aDateAndTime + aDate + aTime + TDateTime(aJustAFloat);
end;
function TMyObject.ReverseString(const aString: string; const aUpperCase: Boolean): string;
begin
Result := System.StrUtils.ReverseString(aString);
if aUpperCase then
Result := Result.ToUpper;
end;
function TMyObject.SavePerson(const aPerson: TJsonObject): Integer;

View File

@ -0,0 +1,107 @@
unit MainControllerU;
interface
uses
MVCFramework, MVCFramework.Commons;
type
[MVCPath('/api')]
TMainController = class(TMVCController)
public
[MVCPath('/')]
[MVCHTTPMethod([httpGET])]
procedure Index;
[MVCPath('/reversedstrings/($Value)')]
[MVCHTTPMethod([httpGET])]
procedure GetReversedString(const Value: String);
protected
procedure OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean); override;
procedure OnAfterAction(Context: TWebContext; const AActionName: string); override;
public
//Sample CRUD Actions for a "Customer" entity
[MVCPath('/customers')]
[MVCHTTPMethod([httpGET])]
procedure GetCustomers;
[MVCPath('/customers/($id)')]
[MVCHTTPMethod([httpGET])]
procedure GetCustomer(id: Integer);
[MVCPath('/customers')]
[MVCHTTPMethod([httpPOST])]
procedure CreateCustomer;
[MVCPath('/customers/($id)')]
[MVCHTTPMethod([httpPUT])]
procedure UpdateCustomer(id: Integer);
[MVCPath('/customers/($id)')]
[MVCHTTPMethod([httpDELETE])]
procedure DeleteCustomer(id: Integer);
end;
implementation
uses
System.SysUtils, MVCFramework.Logger, System.StrUtils;
procedure TMainController.Index;
begin
//use Context property to access to the HTTP request and response
Render('Hello DelphiMVCFramework World');
end;
procedure TMainController.GetReversedString(const Value: String);
begin
Render(System.StrUtils.ReverseString(Value.Trim));
end;
procedure TMainController.OnAfterAction(Context: TWebContext; const AActionName: string);
begin
{ Executed after each action }
inherited;
end;
procedure TMainController.OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean);
begin
{ Executed before each action
if handled is true (or an exception is raised) the actual
action will not be called }
inherited;
end;
//Sample CRUD Actions for a "Customer" entity
procedure TMainController.GetCustomers;
begin
//todo: render a list of customers
end;
procedure TMainController.GetCustomer(id: Integer);
begin
//todo: render the customer by id
end;
procedure TMainController.CreateCustomer;
begin
//todo: create a new customer
end;
procedure TMainController.UpdateCustomer(id: Integer);
begin
//todo: update customer by id
end;
procedure TMainController.DeleteCustomer(id: Integer);
begin
//todo: delete customer by id
end;
end.

View File

@ -0,0 +1,8 @@
object MyWebModule: TMyWebModule
OldCreateOrder = False
OnCreate = WebModuleCreate
OnDestroy = WebModuleDestroy
Actions = <>
Height = 230
Width = 415
end

View File

@ -0,0 +1,97 @@
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
MainControllerU,
System.IOUtils,
MVCFramework.Commons,
LoggerPro.FileAppender,
LoggerPro,
MVCFramework.Middleware.Analytics;
var
GLogWriter: ILogWriter = nil;
GLock: TObject = nil;
function GetLoggerForAnalytics: ILogWriter;
begin
if GLogWriter = nil then
begin
TMonitor.Enter(GLock);
try
if GLogWriter = nil then // double check locking (https://en.wikipedia.org/wiki/Double-checked_locking)
begin
GLogWriter := BuildLogWriter([TLoggerProFileAppender.Create(5, 2000, AppPath + 'analytics')]);
end;
finally
TMonitor.Exit(GLock);
end;
end;
Result := GLogWriter;
end;
procedure TMyWebModule.WebModuleCreate(Sender: TObject);
begin
FMVC := TMVCEngine.Create(Self,
procedure(Config: TMVCConfig)
begin
// enable static files
Config[TMVCConfigKey.DocumentRoot] := TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), 'www');
// 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';
// Enable Server Signature in response
Config[TMVCConfigKey.ExposeServerSignature] := 'false';
// Define a default URL for requests that don't map to a route or a file (useful for client side web app)
Config[TMVCConfigKey.FallbackResource] := 'index.html';
end);
FMVC.AddController(TMainController).AddMiddleware(TMVCAnalyticsMiddleware.Create(GetLoggerForAnalytics));
end;
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
begin
FMVC.Free;
end;
initialization
GLock := TObject.Create;
finalization
GLock.Free;
end.

View File

@ -0,0 +1 @@
This is an HTML file

View File

@ -0,0 +1,110 @@
program middleware_analytics;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
MVCFramework.Logger,
MVCFramework.Commons,
MVCFramework.REPLCommandsHandlerU,
Web.ReqMulti,
Web.WebReq,
Web.WebBroker,
IdHTTPWebBrokerBridge,
MainControllerU in 'MainControllerU.pas',
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule},
MVCFramework.Middleware.Analytics in '..\..\sources\MVCFramework.Middleware.Analytics.pas';
{$R *.res}
procedure RunServer(APort: Integer);
var
lServer: TIdHTTPWebBrokerBridge;
lCustomHandler: TMVCCustomREPLCommandsHandler;
lCmd: string;
begin
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
if ParamCount >= 1 then
lCmd := ParamStr(1)
else
lCmd := 'start';
lCustomHandler := function(const Value: String; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult
begin
Handled := False;
Result := THandleCommandResult.Unknown;
// Write here your custom command for the REPL using the following form...
// ***
// Handled := False;
// if (Value = 'apiversion') then
// begin
// REPLEmit('Print my API version number');
// Result := THandleCommandResult.Continue;
// Handled := True;
// end
// else if (Value = 'datetime') then
// begin
// REPLEmit(DateTimeToStr(Now));
// Result := THandleCommandResult.Continue;
// Handled := True;
// end;
end;
LServer := TIdHTTPWebBrokerBridge.Create(nil);
try
LServer.DefaultPort := APort;
{ more info about MaxConnections
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_MaxConnections.html }
LServer.MaxConnections := 0;
{ more info about ListenQueue
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html }
LServer.ListenQueue := 200;
WriteLn('Write "quit" or "exit" to shutdown the server');
repeat
if lCmd.IsEmpty then
begin
Write('-> ');
ReadLn(lCmd)
end;
try
case HandleCommand(lCmd.ToLower, LServer, lCustomHandler) of
THandleCommandResult.Continue:
begin
Continue;
end;
THandleCommandResult.Break:
begin
Break;
end;
THandleCommandResult.Unknown:
begin
REPLEmit('Unknown command: ' + lCmd);
end;
end;
finally
lCmd := '';
end;
until 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.

View File

@ -0,0 +1,568 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{3A8C1730-9018-4F65-8B73-27F32E592FE3}</ProjectGuid>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>middleware_analytics.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
<Base_Android>true</Base_Android>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Base)'=='true') or '$(Base_iOSDevice32)'!=''">
<Base_iOSDevice32>true</Base_iOSDevice32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''">
<Base_iOSDevice64>true</Base_iOSDevice64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Base)'=='true') or '$(Base_iOSSimulator)'!=''">
<Base_iOSSimulator>true</Base_iOSSimulator>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Linux64' and '$(Base)'=='true') or '$(Base_Linux64)'!=''">
<Base_Linux64>true</Base_Linux64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
<Base_OSX32>true</Base_OSX32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_UsePackage>RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
<UsingDelphiRTL>true</UsingDelphiRTL>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
<DCC_UnitSearchPath>$(DMVC);$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<DCC_Framework>VCL;$(DCC_Framework)</DCC_Framework>
<SanitizedProjectName>middleware_analytics</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android)'!=''">
<DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;DbxCommonDriver;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
<EnabledSysJars>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-ads-7.0.0.dex.jar;google-play-services-analytics-7.0.0.dex.jar;google-play-services-base-7.0.0.dex.jar;google-play-services-identity-7.0.0.dex.jar;google-play-services-maps-7.0.0.dex.jar;google-play-services-panorama-7.0.0.dex.jar;google-play-services-plus-7.0.0.dex.jar;google-play-services-wallet-7.0.0.dex.jar</EnabledSysJars>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;DbxCommonDriver;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;rtcSDK;bindcompfmx;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;rtcSDK_DBA;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;DbxCommonDriver;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;DbxCommonDriver;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Linux64)'!=''">
<DCC_UsePackage>FireDACADSDriver;rtcSDK;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;inetdb;emsedge;dbexpress;IndyCore;dsnap;DataSnapCommon;DataSnapConnectors;bindengine;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;rtcSDK_DBA;IndySystem;FireDACDb2Driver;FireDACInfxDriver;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;rtl;DbxClientDriver;CustomIPTransport;bindcomp;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;IndyProtocols;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_OSX32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;FireDACDSDriver;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;OverbyteIcsD102Run;vclactnband;vclFireDAC;tethering;svnui;FireDACADSDriver;rtcSDK;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;inetdb;MQTTComponents;VirtualTreesDR;RaizeComponentsVcl;emsedge;RaizeComponentsVclDb;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;Package1;DataSnapConnectors;VCLRESTComponents;JclDeveloperTools;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;rtcSDK_DBA;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;DMVC_IDE_Expert_D102Tokyo;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;Jcl;emshosting;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;SynEditDR;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;JclVcl;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;JclContainers;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;OverbyteIcsD102Run;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;inetdb;VirtualTreesDR;RaizeComponentsVcl;emsedge;RaizeComponentsVclDb;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;emshosting;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;SynEditDR;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="MainControllerU.pas"/>
<DCCReference Include="WebModuleU.pas">
<Form>MyWebModule</Form>
<FormType>dfm</FormType>
<DesignClass>TWebModule</DesignClass>
</DCCReference>
<DCCReference Include="..\..\sources\MVCFramework.Middleware.Analytics.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Console</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">middleware_analytics.dpr</Source>
</Source>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win32\Debug\middleware_analytics.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>middleware_analytics.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
</Deployment>
<Platforms>
<Platform value="Android">False</Platform>
<Platform value="iOSDevice32">False</Platform>
<Platform value="iOSDevice64">False</Platform>
<Platform value="iOSSimulator">False</Platform>
<Platform value="Linux64">False</Platform>
<Platform value="OSX32">False</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -0,0 +1,260 @@
unit DAL;
interface
uses
System.JSON,
MVCFramework.SystemJSONUtils,
System.Generics.Collections,
MVCFramework.Serializer.Commons;
type
[MVCNameCase(ncLowerCase)]
TPerson = class
private
FFirstName: string;
FLastName: string;
FAge: Integer;
FItems: string;
FGUID: string;
procedure SetFirstName(const Value: string);
procedure SetLastName(const Value: string);
procedure SetAge(const Value: Integer);
procedure SetGUID(const Value: string);
procedure SetItems(const Value: string);
public
[MVCNameAs('first_name')]
property FirstName: string read FFirstName write SetFirstName;
[MVCNameAs('last_name')]
property LastName: string read FLastName write SetLastName;
property Age: Integer read FAge write SetAge;
property Items: string read FItems write SetItems;
property GUID: string read FGUID write SetGUID;
end;
TPeople = class(TObjectList<TPerson>)
end;
TDevice = class
private
fDeviceName: string;
fSelected: Boolean;
public
property DeviceName: string read fDeviceName write fDeviceName;
property Selected: Boolean read fSelected write fSelected;
constructor Create(aDeviceName: string; aSelected: Boolean);
end;
TDeviceList = class(TObjectList<TDevice>)
public
function Contains(const aDeviceName: string): Boolean;
function IndexOf(const aDeviceName: string): Integer;
end;
IPeopleDAL = interface
['{3E534A3E-EAEB-44ED-B74E-EFBBAAAE11B4}']
function GetPeople: TPeople;
procedure AddPerson(FirstName, LastName: string; Age: Integer; Items: TArray<string>);
procedure DeleteByGUID(GUID: string);
function GetPersonByGUID(GUID: string): TPerson;
function GetDevicesList: TDeviceList;
end;
TPeopleDAL = class(TInterfacedObject, IPeopleDAL)
private const
DATAFILE: string = 'people.data';
public
function GetPeople: TPeople;
procedure AddPerson(FirstName, LastName: string; Age: Integer; Items: TArray<string>);
procedure DeleteByGUID(GUID: string);
function GetPersonByGUID(GUID: string): TPerson;
function GetDevicesList: TDeviceList;
end;
TServicesFactory = class sealed
class function GetPeopleDAL: IPeopleDAL;
end;
implementation
uses
System.SyncObjs,
System.IOUtils,
MVCFramework.Serializer.Defaults,
System.SysUtils;
var
// Hey! The storage is a simple json file, so some synchronization is needed
_CS: TCriticalSection = nil;
{ TSimpleDAL }
procedure TPeopleDAL.AddPerson(FirstName, LastName: string; Age: Integer; Items: TArray<string>);
var
lPeople: TPeople;
lPerson: TPerson;
begin
_CS.Enter;
try
lPeople := GetPeople;
try
lPerson := TPerson.Create;
lPeople.Add(lPerson);
lPerson.FirstName := FirstName;
lPerson.LastName := LastName;
lPerson.Age := Age;
lPerson.Items := string.Join(',', Items);
lPerson.GUID := TGuid.NewGuid.ToString.Replace('{', '').Replace('}', '').Replace('-', '');
TFile.WriteAllText(DATAFILE, GetDefaultSerializer.SerializeCollection(lPeople));
finally
lPeople.Free;
end;
finally
_CS.Leave;
end;
end;
class function TServicesFactory.GetPeopleDAL: IPeopleDAL;
begin
Result := TPeopleDAL.Create;
end;
procedure TPeopleDAL.DeleteByGUID(GUID: string);
var
LJPeople: TPeople;
I: Integer;
begin
_CS.Enter;
try
LJPeople := GetPeople;
try
for I := 0 to LJPeople.Count - 1 do
begin
if LJPeople[I].GUID = GUID then
begin
LJPeople.Delete(i);
break;
end;
end;
TFile.WriteAllText(DATAFILE, GetDefaultSerializer.SerializeCollection(LJPeople));
finally
LJPeople.Free;
end;
finally
_CS.Leave;
end;
end;
function TPeopleDAL.GetDevicesList: TDeviceList;
begin
Result := TDeviceList.Create(true);
Result.Add(TDevice.Create('smartphone', false));
Result.Add(TDevice.Create('dumbphone', false));
Result.Add(TDevice.Create('laptop', false));
Result.Add(TDevice.Create('desktop', false));
end;
function TPeopleDAL.GetPeople: TPeople;
var
LData: string;
begin
_CS.Enter;
try
Result := TPeople.Create;
if TFile.Exists(DATAFILE) then
LData := TFile.ReadAllText(DATAFILE).Trim;
if not LData.IsEmpty then
begin
GetDefaultSerializer.DeserializeCollection(LData, Result, TPerson);
end;
finally
_CS.Leave;
end;
end;
function TPeopleDAL.GetPersonByGUID(GUID: string): TPerson;
var
lPeople: TPeople;
lPerson: TPerson;
begin
Result := nil;
lPeople := GetPeople;
try
for lPerson in lPeople do
begin
if lPerson.GUID = GUID then
begin
Result := lPeople.Extract(lPerson);
Break;
end;
end;
finally
lPeople.Free;
end;
end;
{ TPerson }
procedure TPerson.SetAge(const Value: Integer);
begin
FAge := Value;
end;
procedure TPerson.SetFirstName(const Value: string);
begin
FFirstName := Value;
end;
procedure TPerson.SetGUID(const Value: string);
begin
FGUID := Value;
end;
procedure TPerson.SetItems(const Value: string);
begin
FItems := Value;
end;
procedure TPerson.SetLastName(const Value: string);
begin
FLastName := Value;
end;
{ TDevice }
constructor TDevice.Create(aDeviceName: string; aSelected: Boolean);
begin
inherited Create;
fDeviceName := aDeviceName;
fSelected := aSelected;
end;
{ TDeviceList }
function TDeviceList.Contains(const aDeviceName: string): Boolean;
begin
Result := IndexOf(aDeviceName) > -1;
end;
function TDeviceList.IndexOf(const aDeviceName: string): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Self.Count - 1 do
begin
if SameText(Self[i].DeviceName, aDeviceName) then
Exit(i);
end;
end;
initialization
_CS := TCriticalSection.Create;
finalization
_CS.Free;
end.

View File

@ -0,0 +1,58 @@
program ServerSideViews;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
{$IFDEF MSWINDOWS}
Winapi.ShellAPI,
Winapi.Windows,
{$ENDIF }
IdHTTPWebBrokerBridge,
Web.WebReq,
Web.WebBroker,
WebModuleU in 'WebModuleU.pas' {WebModule1: TWebModule},
WebSiteControllerU in 'WebSiteControllerU.pas',
DAL in 'DAL.pas',
MyDataModuleU in '..\renders\MyDataModuleU.pas' {MyDataModule: TDataModule};
{$R *.res}
procedure RunServer(APort: Integer);
var
LServer: TIdHTTPWebBrokerBridge;
begin
ReportMemoryLeaksOnShutdown := True;
Writeln(Format('Starting HTTP Server on 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', 'http://localhost:8080', nil, nil, SW_SHOW);
{$ENDIF}
ReadLn;
finally
LServer.Free;
end;
end;
begin
ReportMemoryLeaksOnShutdown := True;
try
if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass;
RunServer(8080);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

View File

@ -0,0 +1,502 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{C829684B-145E-49F2-8C37-2562C6C5904E}</ProjectGuid>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>ServerSideViews.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
<SanitizedProjectName>ServerSideViews</SanitizedProjectName>
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName)</VerInfo_Keys>
<Manifest_File>None</Manifest_File>
<DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;frxe23;vclFireDAC;emsclientfiredac;DataSnapFireDAC;svnui;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;ipstudiowinwordxp;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;DelphiCookbookListViewAppearance;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;bdertl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;frxTee23;JclDeveloperTools;vclie;CPortLibDXE;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;Jcl;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;ipstudiowinclient;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DTKANPRPackage;DBXSybaseASADriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;SampleListViewMultiDetailAppearancePackage;bindcomp;appanalytics;ipstudiowin;DBXInformixDriver;officeXPrt;IndyIPClient;bindcompvcl;frxDB23;vcldbx;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;JclVcl;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;frx23;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;ipstudiowinclient;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;ipstudiowin;DBXInformixDriver;officeXPrt;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>None</Manifest_File>
<DCC_RemoteDebug>false</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="WebModuleU.pas">
<Form>WebModule1</Form>
<DesignClass>TWebModule</DesignClass>
</DCCReference>
<DCCReference Include="WebSiteControllerU.pas"/>
<DCCReference Include="DAL.pas"/>
<DCCReference Include="..\renders\MyDataModuleU.pas">
<Form>MyDataModule</Form>
<FormType>dfm</FormType>
<DesignClass>TDataModule</DesignClass>
</DCCReference>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Console</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">ServerSideViews.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k230.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp230.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k230.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="bin\ServerSideViews.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>ServerSideViews.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeX86File"/>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -0,0 +1,13 @@
object WebModule1: TWebModule1
OldCreateOrder = False
OnCreate = WebModuleCreate
OnDestroy = WebModuleDestroy
Actions = <
item
Default = True
Name = 'DefaultHandler'
PathInfo = '/'
end>
Height = 230
Width = 415
end

View File

@ -0,0 +1,65 @@
unit WebModuleU;
interface
uses System.SysUtils, System.Classes, Web.HTTPApp, MVCFramework;
type
TWebModule1 = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
FMVCEngine: TMVCEngine;
{ Private declarations }
public
{ Public declarations }
end;
var
WebModuleClass: TComponentClass = TWebModule1;
implementation
uses
MVCFramework.View.Renderers.Mustache, WebSiteControllerU, MVCFramework.Commons;
{ %CLASSGROUP 'Vcl.Controls.TControl' }
{$R *.dfm}
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
FMVCEngine := TMVCEngine.Create(Self,
procedure(Config: TMVCConfig)
begin
// enable static files
Config[TMVCConfigKey.DocumentRoot] :=
ExtractFilePath(GetModuleName(HInstance)) + '\www';
// 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] := 'mustache';
// view path
Config[TMVCConfigKey.ViewPath] := 'templates';
// Enable Server Signature in response
Config[TMVCConfigKey.ExposeServerSignature] := 'true';
end)
.AddController(TWebSiteController)
.SetViewEngine(TMVCMustacheViewEngine);
end;
procedure TWebModule1.WebModuleDestroy(Sender: TObject);
begin
FMVCEngine.Free;
end;
end.

View File

@ -0,0 +1,207 @@
unit WebSiteControllerU;
interface
uses
MVCFramework, System.Diagnostics, System.JSON, MVCFramework.Commons;
type
[MVCPath('/')]
TWebSiteController = class(TMVCController)
protected
procedure OnBeforeAction(Context: TWebContext; const AActionNAme: string;
var Handled: Boolean); override;
procedure GeneratePeopleListAsCSV;
public
[MVCPath('/people')]
[MVCHTTPMethods([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_HTML)]
procedure PeopleList;
[MVCPath('/people')]
[MVCHTTPMethods([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_CSV)]
// RESTful API, requires ACCEPT=text/csv
procedure ExportPeopleListAsCSV_API;
[MVCPath('/people/formats/csv')]
[MVCHTTPMethods([httpGET])]
// Route usable by the browser, doesn't requires ACCEPT=text/csv
procedure ExportPeopleListAsCSV;
[MVCPath('/people')]
[MVCHTTPMethods([httpPOST])]
[MVCConsumes(TMVCMediaType.APPLICATION_FORM_URLENCODED)]
procedure SavePerson;
[MVCPath('/deleteperson')]
[MVCHTTPMethods([httpPOST])]
[MVCConsumes(TMVCMediaType.APPLICATION_FORM_URLENCODED)]
procedure DeletePerson;
[MVCPath('/new')]
[MVCHTTPMethods([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_HTML)]
procedure NewPerson;
[MVCPath('/edit/($guid)')]
[MVCHTTPMethods([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_HTML)]
procedure EditPerson(guid: string);
[MVCPath('/')]
[MVCHTTPMethods([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_HTML)]
procedure Index;
end;
implementation
{ TWebSiteController }
uses DAL, System.SysUtils, Web.HTTPApp;
procedure TWebSiteController.DeletePerson;
var
lGUID: string;
LDAL: IPeopleDAL;
begin
lGUID := Context.Request.Params['guid'];
LDAL := TServicesFactory.GetPeopleDAL;
LDAL.DeleteByGUID(lGUID);
Redirect('/people');
end;
procedure TWebSiteController.EditPerson(guid: string);
var
LDAL: IPeopleDAL;
lPerson: TPerson;
lDevices: TDeviceList;
lItem: TDevice;
begin
LDAL := TServicesFactory.GetPeopleDAL;
lPerson := LDAL.GetPersonByGUID(guid);
try
lDevices := LDAL.GetDevicesList;
try
ViewData['person'] := lPerson;
for lItem in lDevices do
begin
lItem.Selected := lPerson.Items.Contains(lItem.DeviceName);
end;
ViewData['deviceslist'] := lDevices;
LoadView(['header', 'editperson', 'footer']);
RenderResponseStream;
finally
lDevices.Free;
end;
finally
lPerson.Free;
end;
end;
procedure TWebSiteController.ExportPeopleListAsCSV;
begin
GeneratePeopleListAsCSV;
// define the correct behaviour to download the csv inside the browser
ContentType := TMVCMediaType.TEXT_CSV;
Context.Response.CustomHeaders.Values['Content-Disposition'] :=
'attachment; filename=people.csv';
end;
procedure TWebSiteController.ExportPeopleListAsCSV_API;
begin
GeneratePeopleListAsCSV;
end;
procedure TWebSiteController.GeneratePeopleListAsCSV;
var
LDAL: IPeopleDAL;
lPeople: TPeople;
begin
LDAL := TServicesFactory.GetPeopleDAL;
lPeople := LDAL.GetPeople;
try
ViewData['people'] := lPeople;
LoadView(['people_header.csv', 'people_list.csv']);
RenderResponseStream; // rember to call RenderResponseStream!!!
finally
lPeople.Free;
end;
end;
procedure TWebSiteController.Index;
begin
Redirect('/people');
end;
procedure TWebSiteController.NewPerson;
var
lDAL: IPeopleDAL;
lDevices: TDeviceList;
begin
lDAL := TServicesFactory.GetPeopleDAL;
lDevices := LDAL.GetDevicesList;
try
ViewData['deviceslist'] := lDevices;
LoadView(['header', 'editperson', 'footer']);
RenderResponseStream;
finally
lDevices.Free;
end;
end;
procedure TWebSiteController.OnBeforeAction(Context: TWebContext;
const AActionNAme: string; var Handled: Boolean);
begin
inherited;
ContentType := 'text/html';
Handled := False;
end;
procedure TWebSiteController.PeopleList;
var
LDAL: IPeopleDAL;
lPeople: TPeople;
begin
LDAL := TServicesFactory.GetPeopleDAL;
lPeople := LDAL.GetPeople;
try
ViewData['people'] := lPeople;
LoadView(['header', 'people_list', 'footer']);
RenderResponseStream; // rember to call RenderResponseStream!!!
finally
lPeople.Free;
end;
end;
procedure TWebSiteController.SavePerson;
var
LFirstName: string;
LLastName: string;
LAge: string;
LPeopleDAL: IPeopleDAL;
lDevices: TArray<string>;
begin
LFirstName := Context.Request.Params['first_name'].Trim;
LLastName := Context.Request.Params['last_name'].Trim;
LAge := Context.Request.Params['age'];
lDevices := Context.Request.ParamsMulti['items'];
if LFirstName.IsEmpty or LLastName.IsEmpty or LAge.IsEmpty then
begin
{ TODO -oDaniele -cGeneral : Show how to properly render an exception }
raise EMVCException.Create('Invalid data',
'First name, last name and age are not optional', 0);
end;
LPeopleDAL := TServicesFactory.GetPeopleDAL;
LPeopleDAL.AddPerson(LFirstName, LLastName, LAge.ToInteger(), lDevices);
Redirect('/people');
end;
end.

View File

@ -0,0 +1 @@
[{"first_name":"Bruce","last_name":"Banner","age":56,"items":"smartphone,dumbphone","guid":"2290EE213DFB4855894A3FC91FE52C17"},{"first_name":"Sue","last_name":"Storm","age":32,"items":"desktop","guid":"09162F3E925B4C529282F47DFDB5EF0F"},{"first_name":"Reed","last_name":"Richards","age":45,"items":"laptop,smartphone","guid":"298CE047B4C24D67B29710BF4ABE290C"},{"first_name":"Scott","last_name":"Summers","age":54,"items":"desktop","guid":"3DACB879E83749EDA68389EBA2286A13"},{"first_name":"Daniele","last_name":"Teti","age":40,"items":"","guid":"722E3103AB6141E3B04445593F5AD274"},{"first_name":"Daniele","last_name":"Teti","age":40,"items":"","guid":"FB8F41793F724E08A546BB02BA5676E9"}]

View File

@ -0,0 +1,78 @@
<script>
function doDelete(id) {
if (confirm('Are you sure?')) {
let form = document.getElementById("myForm");
form.action = "/deleteperson";
form.submit();
}
}
</script>
<div class="row_fluid">
<div class="col-sm-12">
<form class="form form-horizontal" id="myForm" name="myForm" method="POST" action="/people">
<input type="hidden" value="{{person.guid}}" name="guid">
<div class="row">
<div class="col-sm-offset-2 col-sm-8">
{{^person}}
<h3>New Person</h3>
{{/person}} {{#person}}
<h3>Edit Person</h3>
{{/person}}
</div>
</div>
<div class="row">
<div class="form-group">
<label for="first_name" class="col-sm-2 control-label">First name</label>
<div class="col-sm-4">
<input type="text" value="{{person.first_name}}" class="form-control" id="first_name" placeholder="First name" name="first_name">
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="last_name" class="col-sm-2 control-label">Last name</label>
<div class="col-sm-4">
<input type="text" value="{{person.last_name}}" class="form-control" id="last_name" placeholder="Last name" name="last_name">
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="age" class="col-sm-2 control-label">Age</label>
<div class="col-sm-4">
<input type="number" value="{{person.age}}" class="form-control" id="age" placeholder="Age" name="age">
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label for="items" class="col-sm-2 control-label">Devices</label>
<div class="col-sm-4">
<select name="items" multiple class="form-control">
{{#deviceslist}}
<option value="{{devicename}}" {{#selected}}selected{{/selected}}>{{devicename}}</option>
{{/deviceslist}}
</select>
<span style="font-size: 80%">(Ctrl+Click to select multiple devices)</span>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-2">
<button type="button" class="btn btn-default btn-block" onclick="history.back()">Return to the list</button>
</div>
<div class="col-sm-2">
{{#person}}
<button type="button" onclick="doDelete()" class="btn btn-primary btn-block">Delete</button> {{/person}} {{^person}}
<button type="submit" class="btn btn-primary btn-block">Save</button> {{/person}}
</div>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,22 @@
<div class="row_fluid">
<div class="col-sm-12">
<div style="height: 100px"></div>
</div>
</div>
<div class="row_fluid">
<div class="col-sm-12">
<span>N.B. All these views are UTF-8 encoded with BOM</span>
</div>
<div class="col-sm-8 bg-primary">
<span>Powered by DMVCFramework</span>
</div>
<div class="col-sm-4 bg-success">
<span>Server Side Views</span>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<header>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<style>
body {
padding: 20px 50px 20px 50px;
}
</style>
</header>
<body>
<div id="main" class="container">
<h1>Server Side Views Primer <small>DMVCFramework</small></h1>

View File

@ -0,0 +1 @@
guid;first_name;last_name;age

View File

@ -0,0 +1,2 @@
{{#people}}{{guid}};"{{first_name}}";"{{last_name}}";{{age}}
{{/people}}

View File

@ -0,0 +1,41 @@
<div class="row_fluid">
<div class="col-sm-12">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>First name</th>
<th>Last name</th>
<th>Age</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{{^people}}
<tr>
<td class="text-center" colspan="5">&lt;&lt;No People Found&gt;&gt;</td>
</tr>
{{/people}} {{#people}}
<tr>
<td>{{-index}}</td>
<td>{{first_name}}</td>
<td>{{last_name}}</td>
<td>{{age}}</td>
<td class="text-right">
<a class="btn btn-default" href="/edit/{{guid}}"><span class="glyphicon glyphicon-pencil"></span> View</a>
</td>
</tr>
{{/people}}
</tbody>
</table>
</div>
</div>
<br>
<div class="row_fluid">
<div class="col-sm-2">
<a class="btn btn-default btn-block" href="/people/formats/csv">Export as CSV</a>
</div>
<div class="col-sm-2 col-sm-offset-8">
<a class="btn btn-primary btn-block" href="/new">Add New Person</a>
</div>
</div>

View File

@ -8260,3 +8260,4 @@ initialization
JSONFormatSettings.DecimalSeparator := '.';
end.

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
@ -76,6 +76,7 @@ type
end;
MVCTableAttribute = class(MVCActiveRecordCustomAttribute)
public
Name: string;
constructor Create(aName: string);
end;
@ -218,6 +219,7 @@ type
function GetPK: TValue;
class function GetByPK<T: TMVCActiveRecord, constructor>(const aValue: int64): T; overload;
class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64): TMVCActiveRecord; overload;
class function GetScalar(const SQL: string; const Params: array of Variant): Variant;
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload;
class function Select(const aClass: TMVCActiveRecordClass; const SQL: string; const Params: array of Variant)
@ -283,6 +285,7 @@ type
TMVCConnectionsRepository = class(TInterfacedObject, IMVCActiveRecordConnections)
private type
TConnHolder = class
public
Connection: TFDConnection;
OwnsConnection: Boolean;
destructor Destroy; override;
@ -905,6 +908,12 @@ begin
Result := fPrimaryKey.GetValue(Self);
end;
class function TMVCActiveRecord.GetScalar(const SQL: string;
const Params: array of Variant): Variant;
begin
Result := CurrentConnection.ExecSQLScalar(SQL, Params);
end;
function TMVCActiveRecord.CheckAction(const aEntityAction: TMVCEntityAction; const aRaiseException: Boolean): Boolean;
begin
Result := aEntityAction in fEntityAllowedActions;
@ -1437,7 +1446,7 @@ begin
lAR := T.Create;
try
lSQL := lAR.SQLGenerator.CreateSelectSQLByRQL(RQL, lAR.GetMapping).Trim;
LogD(Format('RQL [%s] => SQL [%s]', [RQL, lSQL]));
//LogD(Format('RQL [%s] => SQL [%s]', [RQL, lSQL]));
if lSQL.StartsWith('where', True) then
lSQL := lSQL.Remove(0, 5).Trim;
Result := Where<T>(lSQL, []);
@ -1772,3 +1781,4 @@ gCtx.Free;
gLock.Free;
end.

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
@ -42,7 +42,6 @@ uses
{$I dmvcframeworkbuildconsts.inc}
type
TMVCHTTPMethodType = (httpGET, httpPOST, httpPUT, httpDELETE, httpHEAD, httpOPTIONS, httpPATCH, httpTRACE);
@ -110,7 +109,7 @@ type
URL_MAPPED_PARAMS_ALLOWED_CHARS = ' àèéùòì@\[\]\{\}\(\)\=;&#\.\_\,%\w\d\x2D\x3A';
OneMiB = 1048576;
OneKiB = 1024;
DEFAULT_MAX_REQUEST_SIZE = OneMiB * 5; //5 MiB
DEFAULT_MAX_REQUEST_SIZE = OneMiB * 5; // 5 MiB
end;
TMVCConfigKey = record
@ -130,7 +129,7 @@ type
SessionType = 'session_type';
FallbackResource = 'fallback_resource';
MaxEntitiesRecordCount = 'max_entities_record_count';
MaxRequestSize = 'max_request_size'; //bytes
MaxRequestSize = 'max_request_size'; // bytes
end;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
@ -343,8 +342,7 @@ type
end;
TMVCStringDictionary = class
strict
private
strict private
function GetItems(const Key: string): string;
procedure SetItems(const Key, Value: string);
protected
@ -354,7 +352,8 @@ type
destructor Destroy; override;
procedure Clear;
function AddProperty(const Name, Value: string): TMVCStringDictionary;
function TryGetValue(const Name: string; out Value: string): Boolean;
function TryGetValue(const Name: string; out Value: string): Boolean; overload;
function TryGetValue(const Name: string; out Value: Integer): Boolean; overload;
function Count: Integer;
function GetEnumerator: TDictionary<string, string>.TPairEnumerator;
function ContainsKey(const Key: string): Boolean;
@ -451,7 +450,8 @@ function URLSafeB64Decode(const Value: string): string;
function ByteToHex(AInByte: Byte): string;
function BytesToHex(ABytes: TBytes): string;
procedure SplitContentMediaTypeAndCharset(const aContentType: string; var aContentMediaType: string; var aContentCharSet: string);
procedure SplitContentMediaTypeAndCharset(const aContentType: string; var aContentMediaType: string;
var aContentCharSet: string);
function BuildContentType(const aContentMediaType: string; const aContentCharSet: string): string;
const
@ -467,10 +467,11 @@ var
Lock: TObject;
const
RESERVED_IPS: array [1 .. 11] of array [1 .. 2] of string = (('0.0.0.0', '0.255.255.255'), ('10.0.0.0', '10.255.255.255'),
('127.0.0.0', '127.255.255.255'), ('169.254.0.0', '169.254.255.255'), ('172.16.0.0', '172.31.255.255'), ('192.0.2.0', '192.0.2.255'),
('192.88.99.0', '192.88.99.255'), ('192.168.0.0', '192.168.255.255'), ('198.18.0.0', '198.19.255.255'),
('224.0.0.0', '239.255.255.255'), ('240.0.0.0', '255.255.255.255'));
RESERVED_IPS: array [1 .. 11] of array [1 .. 2] of string = (('0.0.0.0', '0.255.255.255'),
('10.0.0.0', '10.255.255.255'), ('127.0.0.0', '127.255.255.255'), ('169.254.0.0', '169.254.255.255'),
('172.16.0.0', '172.31.255.255'), ('192.0.2.0', '192.0.2.255'), ('192.88.99.0', '192.88.99.255'),
('192.168.0.0', '192.168.255.255'), ('198.18.0.0', '198.19.255.255'), ('224.0.0.0', '239.255.255.255'),
('240.0.0.0', '255.255.255.255'));
implementation
@ -504,7 +505,8 @@ begin
if AIP.IsEmpty then
Exit(0);
lPieces := AIP.Split(['.']);
Result := (StrToInt(lPieces[0]) * 16777216) + (StrToInt(lPieces[1]) * 65536) + (StrToInt(lPieces[2]) * 256) + StrToInt(lPieces[3]);
Result := (StrToInt(lPieces[0]) * 16777216) + (StrToInt(lPieces[1]) * 65536) + (StrToInt(lPieces[2]) * 256) +
StrToInt(lPieces[3]);
end;
// function IP2Long(const AIP: string): UInt32;
@ -559,7 +561,8 @@ begin
Result := Result.ToLower.Replace(' ', '', [rfReplaceAll]);
end;
procedure SplitContentMediaTypeAndCharset(const aContentType: string; var aContentMediaType: string; var aContentCharSet: string);
procedure SplitContentMediaTypeAndCharset(const aContentType: string; var aContentMediaType: string;
var aContentCharSet: string);
var
lContentTypeValues: TArray<string>;
begin
@ -705,7 +708,8 @@ begin
end
end
else
raise EMVCConfigException.Create('DMVCFramework configuration file [' + AFileName + '] does not contain a valid JSONObject');
raise EMVCConfigException.Create('DMVCFramework configuration file [' + AFileName +
'] does not contain a valid JSONObject');
end
else
raise EMVCConfigException.Create('Cannot load DMVCFramework configuration file [' + AFileName + ']');
@ -798,6 +802,13 @@ begin
FDict.AddOrSetValue(Key, Value);
end;
function TMVCStringDictionary.TryGetValue(const Name: string; out Value: Integer): Boolean;
var
lTmp: String;
begin
Result := TryGetValue(Name, lTmp) and TryStrToInt(lTmp, Value);
end;
function TMVCStringDictionary.TryGetValue(const Name: string; out Value: string): Boolean;
begin
Result := FDict.TryGetValue(name, Value);
@ -857,7 +868,8 @@ type
end;
const
GURLSafeBase64CodeTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; { Do not Localize }
GURLSafeBase64CodeTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
{ Do not Localize }
procedure TURLSafeEncode.InitComponent;
begin
@ -969,5 +981,3 @@ finalization
FreeAndNil(Lock);
end.

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
@ -64,7 +64,7 @@ type
procedure AppendFromJSONArrayString(AJSONArrayString: string); overload;
procedure AppendFromJSONArrayString(AJSONArrayString: string; AIgnoredFields: TArray<string>;
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
function AsObjectList<T: class, constructor>(CloseAfterScroll: boolean = false): TObjectList<T>;
function AsObjectList<T: class, constructor>(CloseAfterScroll: boolean = false; OwnsObjects: boolean = true): TObjectList<T>;
function AsObject<T: class, constructor>(CloseAfterScroll: boolean = false): T;
end;
@ -167,16 +167,16 @@ begin
Result := nil;
end;
function TDataSetHelper.AsObjectList<T>(CloseAfterScroll: boolean): TObjectList<T>;
function TDataSetHelper.AsObjectList<T>(CloseAfterScroll: boolean; OwnsObjects: boolean): TObjectList<T>;
var
Objs: TObjectList<T>;
lObjs: TObjectList<T>;
begin
Objs := TObjectList<T>.Create(True);
lObjs := TObjectList<T>.Create(OwnsObjects);
try
TDataSetUtils.DataSetToObjectList<T>(Self, Objs, CloseAfterScroll);
Result := Objs;
TDataSetUtils.DataSetToObjectList<T>(Self, lObjs, CloseAfterScroll);
Result := lObjs;
except
FreeAndNil(Objs);
FreeAndNil(lObjs);
raise;
end;
end;
@ -189,8 +189,6 @@ begin
try
lSerializer := TMVCJsonDataObjectsSerializer.Create;
lSerializer.DeserializeDataSet(AJSONArray, Self, nil, ncAsIs);
// Mapper.JSONArrayToDataSet(AJSONArray, Self, TArray<string>.Create(), false,
// AFieldNamePolicy);
finally
Self.EnableControls;
end;

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
@ -41,6 +41,11 @@ type
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
procedure ClearHTTPHeaders;
function HTTPHeadersCount: Integer;
function SetOnReceiveData(const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
function SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
: IMVCJSONRPCExecutor;
function SetOnValidateServerCertificate(const aOnValidateServerCertificate: TValidateCertificateEvent)
: IMVCJSONRPCExecutor;
end;
TMVCJSONRPCExecutor = class(TInterfacedObject, IMVCJSONRPCExecutor)
@ -52,15 +57,20 @@ type
function GetHTTPRequestHeaders: TList<TNetHeader>;
protected
function InternalExecute(const aJSONRPCObject: IJSONRPCObject): IJSONRPCResponse;
public
constructor Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True); virtual;
destructor Destroy; override;
function ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
procedure ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
// Http headers handling
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
procedure ClearHTTPHeaders;
function HTTPHeadersCount: Integer;
function SetOnReceiveData(const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
function SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
: IMVCJSONRPCExecutor;
function SetOnValidateServerCertificate(const aOnValidateServerCertificate: TValidateCertificateEvent)
: IMVCJSONRPCExecutor;
public
constructor Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True); virtual;
destructor Destroy; override;
end;
implementation
@ -69,7 +79,8 @@ uses
System.Classes,
System.SysUtils;
procedure JSONRPCExec(const aJSONRPCURL: string; const aJSONRPCRequest: IJSONRPCRequest; out aJSONRPCResponse: IJSONRPCResponse);
procedure JSONRPCExec(const aJSONRPCURL: string; const aJSONRPCRequest: IJSONRPCRequest;
out aJSONRPCResponse: IJSONRPCResponse);
var
lSS: TStringStream;
lHttpResp: IHTTPResponse;
@ -80,8 +91,8 @@ begin
lSS.Position := 0;
lHTTP := THTTPClient.Create;
try
lHttpResp := lHTTP.Post('http://localhost:8080/jsonrpc', lSS, nil, [TNetHeader.Create('content-type', 'application/json'),
TNetHeader.Create('accept', 'application/json')]);
lHttpResp := lHTTP.Post('http://localhost:8080/jsonrpc', lSS, nil,
[TNetHeader.Create('content-type', 'application/json'), TNetHeader.Create('accept', 'application/json')]);
if (lHttpResp.StatusCode <> 204) then
begin
aJSONRPCResponse := TJSONRPCResponse.Create;
@ -119,6 +130,7 @@ begin
FURL := aURL;
FHTTP := THTTPClient.Create;
FHTTPRequestHeaders := nil;
SetOnReceiveData(nil).SetOnNeedClientCertificate(nil).SetOnValidateServerCertificate(nil);
end;
destructor TMVCJSONRPCExecutor.Destroy;
@ -174,11 +186,11 @@ begin
end;
Result := nil;
lSS := TStringStream.Create(aJSONRPCObject.AsJSONString);
lSS := TStringStream.Create(aJSONRPCObject.AsJSONString, TEncoding.UTF8);
try
lSS.Position := 0;
lHttpResp := FHTTP.Post(FURL, lSS, nil, [TNetHeader.Create('content-type', 'application/json'),
TNetHeader.Create('accept', 'application/json')] + lCustomHeaders);
lHttpResp := FHTTP.Post(FURL, lSS, nil, [TNetHeader.Create('content-type', 'application/json;charset=utf8'),
TNetHeader.Create('accept', 'application/json;charset=utf8')] + lCustomHeaders);
if (lHttpResp.StatusCode <> HTTP_STATUS.NoContent) then
begin
lJSONRPCResponse := TJSONRPCResponse.Create;
@ -192,4 +204,25 @@ begin
end;
end;
function TMVCJSONRPCExecutor.SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
: IMVCJSONRPCExecutor;
begin
FHTTP.OnNeedClientCertificate := aOnNeedClientCertificate;
Result := Self;
end;
function TMVCJSONRPCExecutor.SetOnReceiveData(
const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
begin
FHTTP.OnReceiveData := aOnReceiveData;
Result := Self;
end;
function TMVCJSONRPCExecutor.SetOnValidateServerCertificate(const aOnValidateServerCertificate
: TValidateCertificateEvent): IMVCJSONRPCExecutor;
begin
FHTTP.OnValidateServerCertificate := aOnValidateServerCertificate;
Result := self;
end;
end.

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

View File

@ -2,7 +2,7 @@
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2018 Daniele Teti and the DMVCFramework Team
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//

Some files were not shown because too many files have changed in this diff Show More