Updated sample (refactored to functional actions when possibile)

This commit is contained in:
Daniele Teti 2024-10-05 14:22:15 +02:00
parent 04acc09039
commit 9c1d483c44
44 changed files with 579 additions and 242 deletions

BIN
samples/_/Image00001.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
samples/_/Image00002.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
samples/_/Image00003.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

@ -4,7 +4,8 @@ interface
uses uses
MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons,
System.Generics.Collections, Data.DB, JsonDataObjects, System.Rtti; System.Generics.Collections, Data.DB, JsonDataObjects, System.Rtti,
System.Classes;
type type
TPersonRec = record TPersonRec = record
@ -43,11 +44,15 @@ type
[MVCPath('/records/multiple')] [MVCPath('/records/multiple')]
function GetMultipleRecords: TArray<TPersonRec>; function GetMultipleRecords: TArray<TPersonRec>;
{ actions returning objects } { actions returning objects and binary data}
[MVCPath('/objects/single')] [MVCPath('/objects/single')]
function GetSingleObject: TPerson; function GetSingleObject: TPerson;
[MVCPath('/objects/multiple')] [MVCPath('/objects/multiple')]
function GetMultipleObjects: TObjectList<TPerson>; function GetMultipleObjects: TObjectList<TPerson>;
[MVCPath('/files/customers/($ID)')]
function GetCustomerPhoto(const ID: Integer): TStream;
[MVCPath('/files/sea/($ID)')]
function GetSeaPhoto(const ID: Integer): TStream;
{ actions returning json } { actions returning json }
[MVCPath('/objects/jsonobject')] [MVCPath('/objects/jsonobject')]
@ -107,10 +112,27 @@ implementation
uses uses
System.SysUtils, MVCFramework.Logger, System.StrUtils, System.DateUtils, System.SysUtils, MVCFramework.Logger, System.StrUtils, System.DateUtils,
MainDMU, FireDAC.Comp.Client, MVCFramework.FireDAC.Utils; MainDMU, FireDAC.Comp.Client, MVCFramework.FireDAC.Utils, System.IOUtils;
{ TMyController } { TMyController }
function TMyController.GetSeaPhoto(const ID: Integer): TStream;
var
lBasePath: String;
begin
lBasePath := TPath.Combine(TPath.Combine(AppPath, '..', '..','..'), '_', 'Image%.5d.jpg');
lBasePath := Format(lBasePath, [ID]);
if not TFile.Exists(lBasePath) then
begin
raise EMVCException.Create(HTTP_STATUS.NotFound, 'File not found');
end
else
begin
ContentType := TMVCMediaType.IMAGE_PNG;
Result := TFileStream.Create(lBasePath, fmOpenRead or fmShareDenyWrite);
end;
end;
function TMyController.GetSingleDataSet: TDataSet; function TMyController.GetSingleDataSet: TDataSet;
begin begin
var lDM := TdmMain.Create(nil); var lDM := TdmMain.Create(nil);
@ -309,6 +331,12 @@ begin
Result := A + B; Result := A + B;
end; end;
function TMyController.GetCustomerPhoto(const ID: Integer): TStream;
begin
ContentType := TMVCMediaType.IMAGE_PNG; // you can also use MVCProduces attribute
Result := TFileStream.Create('..\..\..\_\customer.png', fmOpenRead or fmShareDenyWrite);
end;
function TMyController.GetGeneralException: Integer; function TMyController.GetGeneralException: Integer;
begin begin
raise Exception.Create('This is a general exception'); raise Exception.Create('This is a general exception');

View File

@ -44,8 +44,8 @@ type
// function GetPeopleDataset: TFDMemTable; // function GetPeopleDataset: TFDMemTable;
procedure FillPeopleDataset(const DataSet: TDataSet); procedure FillPeopleDataset(const DataSet: TDataSet);
public public
procedure OnBeforeCallHook(const Context: TWebContext; const JSONRequest: TJDOJsonObject);
procedure OnBeforeRoutingHook(const Context: TWebContext; const JSON: TJDOJsonObject); procedure OnBeforeRoutingHook(const Context: TWebContext; const JSON: TJDOJsonObject);
procedure OnBeforeCallHook(const Context: TWebContext; const JSONRequest: TJDOJsonObject);
procedure OnAfterCallHook(const Context: TWebContext; const JSONResponse: TJDOJsonObject); procedure OnAfterCallHook(const Context: TWebContext; const JSONResponse: TJDOJsonObject);
public public
[MVCDoc('You know, returns aValue1 - aValue2')] [MVCDoc('You know, returns aValue1 - aValue2')]

View File

@ -52,6 +52,21 @@ type
const AAttributes: System.TArray<System.TCustomAttribute>); const AAttributes: System.TArray<System.TCustomAttribute>);
end; end;
// Custom serializer for TSysUserSerializer type
TSysUserSerializer = class(TInterfacedObject, IMVCTypeSerializer)
public
procedure SerializeAttribute(const AElementValue: TValue; const APropertyName: string;
const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
procedure SerializeRoot(const AObject: TObject; out ASerializerObject: TObject;
const AAttributes: System.TArray<System.TCustomAttribute>;
const ASerializationAction: TMVCSerializationAction = nil);
procedure DeserializeAttribute(var AElementValue: TValue; const APropertyName: string;
const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
procedure DeserializeRoot(const ASerializerObject: TObject; const AObject: TObject;
const AAttributes: System.TArray<System.TCustomAttribute>);
end;
// Custom serializer for TNullableAliasSerializer type // Custom serializer for TNullableAliasSerializer type
TNullableAliasSerializer = class(TInterfacedObject, IMVCTypeSerializer) TNullableAliasSerializer = class(TInterfacedObject, IMVCTypeSerializer)
public public
@ -170,4 +185,34 @@ begin
raise EMVCSerializationException.CreateFmt('%s cannot be used as root object', [ClassName]); raise EMVCSerializationException.CreateFmt('%s cannot be used as root object', [ClassName]);
end; end;
{ TSysUserSerializer }
procedure TSysUserSerializer.DeserializeAttribute(var AElementValue: TValue; const APropertyName: string;
const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
begin
end;
procedure TSysUserSerializer.DeserializeRoot(const ASerializerObject, AObject: TObject;
const AAttributes: System.TArray<System.TCustomAttribute>);
begin
end;
procedure TSysUserSerializer.SerializeAttribute(const AElementValue: TValue; const APropertyName: string;
const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
begin
(ASerializerObject as TJDOJsonObject).S['prop'] := 'hello there attribute';
end;
procedure TSysUserSerializer.SerializeRoot(const AObject: TObject; out ASerializerObject: TObject;
const AAttributes: System.TArray<System.TCustomAttribute>; const ASerializationAction: TMVCSerializationAction);
var
lJObj: TJDOJsonObject;
begin
lJObj := (ASerializerObject as TJDOJsonObject);
lJObj.S['username'] := TSysUser(AObject).UserName;
lJObj.S['roles'] := String.Join(',', TSysUser(AObject).Roles);
end;
end. end.

View File

@ -48,8 +48,8 @@ type
// custom serialized type as property Roles // custom serialized type as property Roles
TSysUser = class TSysUser = class
private private
FUserName: string; fUserName: string;
FRoles: TUserRoles; fRoles: TUserRoles;
fRecordAlias: TNullableRecordAlias; fRecordAlias: TNullableRecordAlias;
procedure SetUserName(const Value: string); procedure SetUserName(const Value: string);
function GetUserRoles: TUserRoles; function GetUserRoles: TUserRoles;
@ -61,6 +61,19 @@ type
property RecordAlias: TNullableRecordAlias read fRecordAlias write fRecordAlias; property RecordAlias: TNullableRecordAlias read fRecordAlias write fRecordAlias;
end; end;
TSysUser2 = class
private
FUserName: string;
fRoles: TUserRoles;
fRecordAlias: TNullableRecordAlias;
public
constructor Create(aUserName: string; aRoles: TUserRoles);
property UserName: string read FUserName write FUserName;
// Here we are using the custom-serialized type TUserRoles
property Roles: TUserRoles read fRoles write fRoles;
end;
TArrayTest = class TArrayTest = class
private private
fStrings: TArray<string>; fStrings: TArray<string>;
@ -161,4 +174,13 @@ begin
inherited; inherited;
end; end;
{ TSysUser2 }
constructor TSysUser2.Create(aUserName: string; aRoles: TUserRoles);
begin
inherited Create;
FUserName := aUserName;
fRoles := aRoles;
end;
end. end.

View File

@ -243,8 +243,13 @@ type
procedure RaiseExceptionHTML; procedure RaiseExceptionHTML;
[MVCHTTPMethod([httpGET])] [MVCHTTPMethod([httpGET])]
[MVCPath('/customserializationtype')] [MVCPath('/customserializationtype/root')]
procedure GetCustomSerializationType; procedure GetCustomSerializationTypeROOT;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customserializationtype/attribute')]
procedure GetCustomSerializationTypeATTRIBUTE;
[MVCHTTPMethod([httpGET])] [MVCHTTPMethod([httpGET])]
[MVCPath('/simplearray')] [MVCPath('/simplearray')]
@ -716,9 +721,15 @@ begin
end; end;
end; end;
procedure TRenderSampleController.GetCustomSerializationType; procedure TRenderSampleController.GetCustomSerializationTypeATTRIBUTE;
begin begin
// TSysUser contains a type with a custom serializer // TSysUser2 contains a type with a custom serializer
Render(TSysUser2.Create('daniele', ['poweruser', 'role1', 'role2']), True);
end;
procedure TRenderSampleController.GetCustomSerializationTypeROOT;
begin
// TSysUser is a type with a custom serializer
Render(TSysUser.Create('daniele', ['poweruser', 'role1', 'role2']), True); Render(TSysUser.Create('daniele', ['poweruser', 'role1', 'role2']), True);
end; end;

View File

@ -1,5 +1,4 @@
object WebModule1: TWebModule1 object WebModule1: TWebModule1
OldCreateOrder = False
OnCreate = WebModuleCreate OnCreate = WebModuleCreate
Actions = <> Actions = <>
Height = 344 Height = 344

View File

@ -100,10 +100,13 @@ begin
DMVC.SetViewEngine(TMVCMustacheViewEngine); DMVC.SetViewEngine(TMVCMustacheViewEngine);
// Register a custom serializer for TUserRoles (is compatible only with the default serializer) // Register a custom serializer for TUserRoles (is compatible only with the default serializer)
// DMVC DMVC
// .Serializers .Serializer(TMVCMediaType.APPLICATION_JSON)
// .Items[TMVCMediaType.APPLICATION_JSON] .RegisterTypeSerializer(TypeInfo(TUserRoles), TUserRolesSerializer.Create);
// .RegisterTypeSerializer(TypeInfo(TUserRoles), TUserRolesSerializer.Create);
DMVC
.Serializer(TMVCMediaType.APPLICATION_JSON)
.RegisterTypeSerializer(TypeInfo(TSysUser), TSysUserSerializer.Create);
// You can check how this custom type serializer works // You can check how this custom type serializer works
// calling http://localhost:8080/customserializationtype // calling http://localhost:8080/customserializationtype

View File

@ -36,6 +36,7 @@ uses
Web.WebReq, Web.WebReq,
Web.WebBroker, Web.WebBroker,
MVCFramework.Console, MVCFramework.Console,
MVCFramework.Logger,
WebModuleU in 'WebModuleU.pas' {WebModule1: TWebModule}, WebModuleU in 'WebModuleU.pas' {WebModule1: TWebModule},
RenderSampleControllerU in 'RenderSampleControllerU.pas', RenderSampleControllerU in 'RenderSampleControllerU.pas',
BusinessObjectsU in '..\commons\BusinessObjectsU.pas', BusinessObjectsU in '..\commons\BusinessObjectsU.pas',
@ -55,17 +56,17 @@ procedure RunServer(APort: Integer);
var var
LServer: TIdHTTPWebBrokerBridge; LServer: TIdHTTPWebBrokerBridge;
begin begin
Writeln(Format('Starting HTTP Server or port %d', [APort])); LogI(Format('Starting HTTP Server or port %d', [APort]));
LServer := TIdHTTPWebBrokerBridge.Create(nil); LServer := TIdHTTPWebBrokerBridge.Create(nil);
try try
LServer.DefaultPort := APort; LServer.DefaultPort := APort;
LServer.Active := True; LServer.Active := True;
TextColor(Red); TextColor(Red);
Writeln('DMVCFRAMEWORK VERSION: ', DMVCFRAMEWORK_VERSION); LogI('DMVCFRAMEWORK VERSION: ' + DMVCFRAMEWORK_VERSION);
ResetConsole; ResetConsole;
Writeln('Press RETURN to stop the server'); LogI('Press RETURN to stop the server');
WaitForReturn; WaitForReturn;
Writeln('Stopping...'); LogI('Stopping...');
finally finally
LServer.Free; LServer.Free;
end; end;
@ -74,13 +75,14 @@ end;
begin begin
ReportMemoryLeaksOnShutdown := True; ReportMemoryLeaksOnShutdown := True;
MVCSerializeNulls := True; MVCSerializeNulls := True;
UseConsoleLogger := True;
try try
if WebRequestHandler <> nil then if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass; WebRequestHandler.WebModuleClass := WebModuleClass;
RunServer(8080); RunServer(8080);
except except
on E: Exception do on E: Exception do
Writeln(E.ClassName, ': ', E.Message); LogException(E, E.Message);
end end
end. end.

View File

@ -98,6 +98,8 @@
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<DCC_RemoteDebug>false</DCC_RemoteDebug> <DCC_RemoteDebug>false</DCC_RemoteDebug>
<DCC_DebugDCUs>false</DCC_DebugDCUs>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''"> <PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@ -197,10 +199,8 @@
<VersionInfoKeys Name="theme"/> <VersionInfoKeys Name="theme"/>
</VersionInfoKeys> </VersionInfoKeys>
<Excluded_Packages> <Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k240.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages> <Excluded_Packages Name="$(BDSBIN)\dcloffice2k290.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp240.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages> <Excluded_Packages Name="$(BDSBIN)\dclofficexp290.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k240.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp240.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="5"> <Deployment Version="5">

View File

@ -25,7 +25,7 @@ var
lCurrentEventID: Integer; lCurrentEventID: Integer;
lSSEMessage: TSSEMessage; lSSEMessage: TSSEMessage;
begin begin
Sleep(1000); Sleep(500 + Random(2000));
lSSEMessage.Event := 'stockupdate'; lSSEMessage.Event := 'stockupdate';
lSSEMessage.Data := GetNextDataToSend(StrToIntDef(LastEventID, 0), lCurrentEventID); lSSEMessage.Data := GetNextDataToSend(StrToIntDef(LastEventID, 0), lCurrentEventID);
lSSEMessage.Id := lCurrentEventID.ToString; lSSEMessage.Id := lCurrentEventID.ToString;

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{56928A09-5B7B-4920-ABAA-CB68F0AC2958}</ProjectGuid> <ProjectGuid>{56928A09-5B7B-4920-ABAA-CB68F0AC2958}</ProjectGuid>
<ProjectVersion>20.1</ProjectVersion> <ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>SSESample.dpr</MainSource> <MainSource>SSESample.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
@ -146,7 +146,7 @@
<Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP 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> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="4"> <Deployment Version="5">
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule"/> <DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule"/>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule"/> <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule"/>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule"/> <DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule"/>
@ -160,16 +160,6 @@
<Operation>0</Operation> <Operation>0</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidClasses">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider"> <DeployClass Name="AndroidFileProvider">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\xml</RemoteDir> <RemoteDir>res\xml</RemoteDir>
@ -180,12 +170,6 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile"> <DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir> <RemoteDir>library\lib\armeabi</RemoteDir>

View File

@ -1 +1 @@
[{"first_name":"Daniele","last_name":"Teti","age":43,"devices":[],"guid":"49E8419B66C744529D63DB292389D541"},{"first_name":"Peter","last_name":"Parker","age":23,"devices":[],"guid":"C5489969A04D4AE4B00D4FC50C8ADB5C"},{"first_name":"Bruce","last_name":"Banner","age":50,"devices":[],"guid":"B41D180F30584558B4F4A1AAF849FFA3"},{"first_name":"Sue","last_name":"Storm","age":33,"devices":[],"guid":"3F058118B8C6470D9684E127BC30A84A"},{"first_name":"Scott","last_name":"Summer","age":35,"devices":[],"guid":"3518D8C6F60E42D19C5A7250ADEADC33"},{"first_name":"Reed","last_name":"Richards","age":45,"devices":["smartphone","desktop"],"guid":"09C85C9DEB714476AADB9EB0AD689536"}] [{"first_name":"Daniele","last_name":"Teti","age":43,"devices":[],"guid":"49E8419B66C744529D63DB292389D541"},{"first_name":"Peter","last_name":"Parker","age":23,"devices":[],"guid":"C5489969A04D4AE4B00D4FC50C8ADB5C"},{"first_name":"Bruce","last_name":"Banner","age":50,"devices":[],"guid":"B41D180F30584558B4F4A1AAF849FFA3"},{"first_name":"Sue","last_name":"Storm","age":33,"devices":[],"guid":"3F058118B8C6470D9684E127BC30A84A"},{"first_name":"Scott","last_name":"Summer","age":35,"devices":[],"guid":"3518D8C6F60E42D19C5A7250ADEADC33"},{"first_name":"Reed","last_name":"Richards","age":45,"devices":["smartphone","desktop"],"guid":"09C85C9DEB714476AADB9EB0AD689536"},{"first_name":"Paolino","last_name":"Paperino","age":34,"devices":["dumbphone","laptop"],"guid":"40E3AA589440403C851D28FD649735E8"},{"first_name":"Paolino","last_name":"Paperino","age":34,"devices":["dumbphone","laptop"],"guid":"A9F3E3B5F6D344EC93C47C6E2B721B16"}]

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{180D0369-D404-417C-8F18-6DE283368DE3}</ProjectGuid> <ProjectGuid>{180D0369-D404-417C-8F18-6DE283368DE3}</ProjectGuid>
<ProjectVersion>19.5</ProjectVersion> <ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>CustomSessionSample.dpr</MainSource> <MainSource>CustomSessionSample.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
@ -9,6 +9,7 @@
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms> <TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType> <AppType>Console</AppType>
<ProjectName Condition="'$(ProjectName)'==''">CustomSessionSample</ProjectName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base> <Base>true</Base>
@ -154,7 +155,7 @@
<Excluded_Packages Name="$(BDSBIN)\dclofficexp170.bpl">Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server</Excluded_Packages> <Excluded_Packages Name="$(BDSBIN)\dclofficexp170.bpl">Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server</Excluded_Packages>
</Excluded_Packages> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="4"> <Deployment Version="5">
<DeployFile LocalName="Win32\Debug\CustomSessionSample.exe" Configuration="Debug" Class="ProjectOutput"/> <DeployFile LocalName="Win32\Debug\CustomSessionSample.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployClass Name="AdditionalDebugSymbols"> <DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32"> <Platform Name="OSX32">
@ -164,16 +165,6 @@
<Operation>0</Operation> <Operation>0</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidClasses">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider"> <DeployClass Name="AndroidFileProvider">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\xml</RemoteDir> <RemoteDir>res\xml</RemoteDir>
@ -184,12 +175,6 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile"> <DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir> <RemoteDir>library\lib\armeabi</RemoteDir>
@ -242,6 +227,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashImageDefV21">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles"> <DeployClass Name="AndroidSplashStyles">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -262,6 +257,66 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashStylesV31">
<Platform Name="Android">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconBackground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconForeground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconMonochrome">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconV33">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors"> <DeployClass Name="Android_Colors">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -272,6 +327,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_ColorsDark">
<Platform Name="Android">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon"> <DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir> <RemoteDir>res\drawable</RemoteDir>
@ -442,6 +507,56 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_VectorizedNotificationIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplash">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashDark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31Dark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols"> <DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator"> <Platform Name="iOSSimulator">
<Operation>1</Operation> <Operation>1</Operation>
@ -619,6 +734,9 @@
<Platform Name="Win64"> <Platform Name="Win64">
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
<Platform Name="Win64x">
<Operation>1</Operation>
</Platform>
</DeployClass> </DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug"> <DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
@ -880,6 +998,7 @@
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64x" Name="$(PROJECTNAME)"/>
</Deployment> </Deployment>
<Platforms> <Platforms>
<Platform value="Win32">True</Platform> <Platform value="Win32">True</Platform>

View File

@ -53,7 +53,7 @@ begin
end end
else else
begin begin
RenderStatusMessage(http_status.BadRequest, 'Session not created. Do login first'); Render(http_status.BadRequest, 'Session not created. Do login first');
end; end;
end; end;

View File

@ -7,14 +7,11 @@ uses
System.SysUtils, System.SysUtils,
MVCFramework, MVCFramework,
MVCFramework.Signal, MVCFramework.Signal,
MVCFramework.Logger,
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
Winapi.Windows, Winapi.Windows,
Winapi.ShellAPI, Winapi.ShellAPI,
{$ENDIF} {$ENDIF}
Web.WebReq, Web.WebReq,
Web.WebBroker, Web.WebBroker,
IdHTTPWebBrokerBridge, IdHTTPWebBrokerBridge,
@ -28,7 +25,7 @@ procedure RunServer(APort: Integer);
var var
LServer: TIdHTTPWebBrokerBridge; LServer: TIdHTTPWebBrokerBridge;
begin begin
Writeln(Format('Starting HTTP Server or port %d', [APort])); LogI(Format('Starting HTTP Server or port %d', [APort]));
LServer := TIdHTTPWebBrokerBridge.Create(nil); LServer := TIdHTTPWebBrokerBridge.Create(nil);
try try
LServer.DefaultPort := APort; LServer.DefaultPort := APort;
@ -36,7 +33,7 @@ begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
ShellExecute(0, 'open', PChar('http://localhost:' + IntToStr(APort) + '/login/john'), nil, nil, SW_SHOW); ShellExecute(0, 'open', PChar('http://localhost:' + IntToStr(APort) + '/login/john'), nil, nil, SW_SHOW);
{$ENDIF} {$ENDIF}
Writeln('CTRL+C to stop the server'); LogI('CTRL+C to stop the server');
WaitForTerminationSignal; WaitForTerminationSignal;
EnterInShutdownState; EnterInShutdownState;
finally finally
@ -53,7 +50,7 @@ begin
RunServer(8080); RunServer(8080);
except except
on E: Exception do on E: Exception do
Writeln(E.ClassName, ': ', E.Message); LogI(E.ClassName + ': ' + E.Message);
end end
end. end.

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{F9CBCE21-869A-478F-992C-88FCAC97BC8B}</ProjectGuid> <ProjectGuid>{F9CBCE21-869A-478F-992C-88FCAC97BC8B}</ProjectGuid>
<ProjectVersion>19.5</ProjectVersion> <ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>SessionSample.dpr</MainSource> <MainSource>SessionSample.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
@ -9,6 +9,7 @@
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms> <TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType> <AppType>Console</AppType>
<ProjectName Condition="'$(ProjectName)'==''">SessionSample</ProjectName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base> <Base>true</Base>
@ -153,7 +154,7 @@
<Excluded_Packages Name="$(BDSBIN)\dclofficexp170.bpl">Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server</Excluded_Packages> <Excluded_Packages Name="$(BDSBIN)\dclofficexp170.bpl">Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server</Excluded_Packages>
</Excluded_Packages> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="4"> <Deployment Version="5">
<DeployFile LocalName="Win32\Debug\SessionSample.exe" Configuration="Debug" Class="ProjectOutput"/> <DeployFile LocalName="Win32\Debug\SessionSample.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployClass Name="AdditionalDebugSymbols"> <DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32"> <Platform Name="OSX32">
@ -163,16 +164,6 @@
<Operation>0</Operation> <Operation>0</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidClasses">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider"> <DeployClass Name="AndroidFileProvider">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\xml</RemoteDir> <RemoteDir>res\xml</RemoteDir>
@ -183,12 +174,6 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile"> <DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir> <RemoteDir>library\lib\armeabi</RemoteDir>
@ -241,6 +226,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashImageDefV21">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles"> <DeployClass Name="AndroidSplashStyles">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -261,6 +256,66 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashStylesV31">
<Platform Name="Android">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconBackground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconForeground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconMonochrome">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconV33">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors"> <DeployClass Name="Android_Colors">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -271,6 +326,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_ColorsDark">
<Platform Name="Android">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon"> <DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir> <RemoteDir>res\drawable</RemoteDir>
@ -441,6 +506,56 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_VectorizedNotificationIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplash">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashDark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31Dark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols"> <DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator"> <Platform Name="iOSSimulator">
<Operation>1</Operation> <Operation>1</Operation>
@ -546,6 +661,130 @@
<Operation>0</Operation> <Operation>0</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<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>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<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="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64x">
<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>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSLaunchScreen"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<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>
<DeployClass Name="iOS_AppStore1024"> <DeployClass Name="iOS_AppStore1024">
<Platform Name="iOSDevice64"> <Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir> <RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
@ -746,127 +985,6 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<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>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSLaunchScreen"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<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>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<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="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</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="Android" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/> <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
@ -879,6 +997,7 @@
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/> <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64x" Name="$(PROJECTNAME)"/>
</Deployment> </Deployment>
<Platforms> <Platforms>
<Platform value="Win32">True</Platform> <Platform value="Win32">True</Platform>

View File

@ -16,15 +16,15 @@ type
public public
[MVCPath('/($ID)')] [MVCPath('/($ID)')]
[MVCHTTPMethods([httpGET])] [MVCHTTPMethods([httpGET])]
procedure GetCustomerByID(const ID: Integer); function GetCustomerByID(const ID: Integer): TCustomer;
[MVCPath] [MVCPath]
[MVCHTTPMethods([httpGET])] [MVCHTTPMethods([httpGET])]
procedure GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String); function GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String): TObjectList<TCustomer>;
[MVCPath] [MVCPath]
[MVCHTTPMethods([httpPOST])] [MVCHTTPMethods([httpPOST])]
procedure CreateCustomer([MVCFromBody] const Customer: TCustomer); function CreateCustomer([MVCFromBody] const Customer: TCustomer): IMVCResponse;
[MVCPath('/_bulk')] [MVCPath('/_bulk')]
[MVCHTTPMethods([httpPOST])] [MVCHTTPMethods([httpPOST])]
@ -43,20 +43,20 @@ uses
{ TCustomersController } { TCustomersController }
procedure TCustomersController.CreateCustomer(const Customer: TCustomer); function TCustomersController.CreateCustomer(const Customer: TCustomer): IMVCResponse;
begin begin
Customer.Insert; Customer.Insert;
Render201Created('/api/customers/' + Customer.ID.Value.ToString); Result := CreatedResponse('/api/customers/' + Customer.ID.Value.ToString);
end; end;
procedure TCustomersController.GetCustomerByID(const ID: Integer); function TCustomersController.GetCustomerByID(const ID: Integer): TCustomer;
begin begin
Render(ObjectDict().Add('data', TMVCActiveRecord.GetByPK<TCustomer>(ID))); Result := TMVCActiveRecord.GetByPK<TCustomer>(ID);
end; end;
procedure TCustomersController.GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String); function TCustomersController.GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String): TObjectList<TCustomer>;
begin begin
Render(ObjectDict().Add('data', TMVCActiveRecord.SelectRQL<TCustomer>(RQLFilter, 1000))); Result := TMVCActiveRecord.SelectRQL<TCustomer>(RQLFilter, 1000);
end; end;
procedure TCustomersController.BulkCreateCustomers(const Customers: TObjectList<TCustomer>); procedure TCustomersController.BulkCreateCustomers(const Customers: TObjectList<TCustomer>);

View File

@ -345,11 +345,12 @@ begin
lErrResponse.ClassName, lErrResponse.ClassName,
lErrResponse.AppErrorCode, lErrResponse.AppErrorCode,
nil); nil);
end; end else if aObject = nil then
if Result.IsEmpty then
begin begin
RaiseNotImplemented Result := '';
end else
begin
RaiseNotImplemented;
end; end;
end; end;

View File

@ -2859,30 +2859,37 @@ begin
begin begin
lResponseObject := lInvokeResult.AsObject; lResponseObject := lInvokeResult.AsObject;
try try
// https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-7.0 if lResponseObject <> nil then
if lResponseObject is TDataSet then
begin begin
lSelectedController.Render(TDataSet(lResponseObject), False); // https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-7.0
end if lResponseObject is TDataSet then
else if lResponseObject is TStream then begin
begin lSelectedController.Render(TDataSet(lResponseObject), False);
lContext.Response.RawWebResponse.Content := EmptyStr; end
lContext.Response.RawWebResponse.ContentType := lContext.Response.ContentType; else if lResponseObject is TStream then
lContext.Response.RawWebResponse.ContentStream := TStream(lResponseObject); begin
lContext.Response.RawWebResponse.FreeContentStream := True; lContext.Response.RawWebResponse.Content := EmptyStr;
lResponseObject := nil; //do not free it!! lContext.Response.RawWebResponse.ContentType := lContext.Response.ContentType;
end lContext.Response.RawWebResponse.ContentStream := TStream(lResponseObject);
else if lResponseObject is TMVCResponse then lContext.Response.RawWebResponse.FreeContentStream := True;
begin lResponseObject := nil; //do not free it!!
TMVCRenderer.InternalRenderMVCResponse(lSelectedController, TMVCResponse(lResponseObject)); end
end else if lResponseObject is TMVCResponse then
else if (not lResponseObject.InheritsFrom(TJsonBaseObject)) and TDuckTypedList.CanBeWrappedAsList(lResponseObject, lObjList) then begin
begin TMVCRenderer.InternalRenderMVCResponse(lSelectedController, TMVCResponse(lResponseObject));
lSelectedController.Render(lObjList); end
else if (not lResponseObject.InheritsFrom(TJsonBaseObject)) and TDuckTypedList.CanBeWrappedAsList(lResponseObject, lObjList) then
begin
lSelectedController.Render(lObjList);
end
else
begin
lSelectedController.Render(lResponseObject, False);
end;
end end
else else
begin begin
lSelectedController.Render(lResponseObject, False); lSelectedController.Render(TObject(nil));
end; end;
finally finally
lResponseObject.Free; lResponseObject.Free;