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
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
TPersonRec = record
@ -43,11 +44,15 @@ type
[MVCPath('/records/multiple')]
function GetMultipleRecords: TArray<TPersonRec>;
{ actions returning objects }
{ actions returning objects and binary data}
[MVCPath('/objects/single')]
function GetSingleObject: TPerson;
[MVCPath('/objects/multiple')]
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 }
[MVCPath('/objects/jsonobject')]
@ -107,10 +112,27 @@ implementation
uses
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 }
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;
begin
var lDM := TdmMain.Create(nil);
@ -309,6 +331,12 @@ begin
Result := A + B;
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;
begin
raise Exception.Create('This is a general exception');

View File

@ -44,8 +44,8 @@ type
// function GetPeopleDataset: TFDMemTable;
procedure FillPeopleDataset(const DataSet: TDataSet);
public
procedure OnBeforeCallHook(const Context: TWebContext; const JSONRequest: 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);
public
[MVCDoc('You know, returns aValue1 - aValue2')]

View File

@ -52,6 +52,21 @@ type
const AAttributes: System.TArray<System.TCustomAttribute>);
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
TNullableAliasSerializer = class(TInterfacedObject, IMVCTypeSerializer)
public
@ -170,4 +185,34 @@ begin
raise EMVCSerializationException.CreateFmt('%s cannot be used as root object', [ClassName]);
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.

View File

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

View File

@ -243,8 +243,13 @@ type
procedure RaiseExceptionHTML;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customserializationtype')]
procedure GetCustomSerializationType;
[MVCPath('/customserializationtype/root')]
procedure GetCustomSerializationTypeROOT;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customserializationtype/attribute')]
procedure GetCustomSerializationTypeATTRIBUTE;
[MVCHTTPMethod([httpGET])]
[MVCPath('/simplearray')]
@ -716,9 +721,15 @@ begin
end;
end;
procedure TRenderSampleController.GetCustomSerializationType;
procedure TRenderSampleController.GetCustomSerializationTypeATTRIBUTE;
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);
end;

View File

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

View File

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

View File

@ -36,6 +36,7 @@ uses
Web.WebReq,
Web.WebBroker,
MVCFramework.Console,
MVCFramework.Logger,
WebModuleU in 'WebModuleU.pas' {WebModule1: TWebModule},
RenderSampleControllerU in 'RenderSampleControllerU.pas',
BusinessObjectsU in '..\commons\BusinessObjectsU.pas',
@ -55,17 +56,17 @@ procedure RunServer(APort: Integer);
var
LServer: TIdHTTPWebBrokerBridge;
begin
Writeln(Format('Starting HTTP Server or port %d', [APort]));
LogI(Format('Starting HTTP Server or port %d', [APort]));
LServer := TIdHTTPWebBrokerBridge.Create(nil);
try
LServer.DefaultPort := APort;
LServer.Active := True;
TextColor(Red);
Writeln('DMVCFRAMEWORK VERSION: ', DMVCFRAMEWORK_VERSION);
LogI('DMVCFRAMEWORK VERSION: ' + DMVCFRAMEWORK_VERSION);
ResetConsole;
Writeln('Press RETURN to stop the server');
LogI('Press RETURN to stop the server');
WaitForReturn;
Writeln('Stopping...');
LogI('Stopping...');
finally
LServer.Free;
end;
@ -74,13 +75,14 @@ end;
begin
ReportMemoryLeaksOnShutdown := True;
MVCSerializeNulls := True;
UseConsoleLogger := True;
try
if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass;
RunServer(8080);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
LogException(E, E.Message);
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_Locale>1033</VerInfo_Locale>
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<DCC_DebugDCUs>false</DCC_DebugDCUs>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@ -197,10 +199,8 @@
<VersionInfoKeys Name="theme"/>
</VersionInfoKeys>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k240.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp240.bpl">Embarcadero C++Builder Office XP Servers Package</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 Name="$(BDSBIN)\dcloffice2k290.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp290.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="5">

View File

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

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{56928A09-5B7B-4920-ABAA-CB68F0AC2958}</ProjectGuid>
<ProjectVersion>20.1</ProjectVersion>
<ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>SSESample.dpr</MainSource>
<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>
</Delphi.Personality>
<Deployment Version="4">
<Deployment Version="5">
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule"/>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule"/>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule"/>
@ -160,16 +160,6 @@
<Operation>0</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
@ -180,12 +170,6 @@
<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>

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">
<PropertyGroup>
<ProjectGuid>{180D0369-D404-417C-8F18-6DE283368DE3}</ProjectGuid>
<ProjectVersion>19.5</ProjectVersion>
<ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>CustomSessionSample.dpr</MainSource>
<Base>True</Base>
@ -9,6 +9,7 @@
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
<ProjectName Condition="'$(ProjectName)'==''">CustomSessionSample</ProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(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>
</Delphi.Personality>
<Deployment Version="4">
<Deployment Version="5">
<DeployFile LocalName="Win32\Debug\CustomSessionSample.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
@ -164,16 +165,6 @@
<Operation>0</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
@ -184,12 +175,6 @@
<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>
@ -242,6 +227,16 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
@ -262,6 +257,66 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
@ -272,6 +327,16 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
@ -442,6 +507,56 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
@ -619,6 +734,9 @@
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64x">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
@ -880,6 +998,7 @@
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64x" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{F9CBCE21-869A-478F-992C-88FCAC97BC8B}</ProjectGuid>
<ProjectVersion>19.5</ProjectVersion>
<ProjectVersion>20.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>SessionSample.dpr</MainSource>
<Base>True</Base>
@ -9,6 +9,7 @@
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
<ProjectName Condition="'$(ProjectName)'==''">SessionSample</ProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(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>
</Delphi.Personality>
<Deployment Version="4">
<Deployment Version="5">
<DeployFile LocalName="Win32\Debug\SessionSample.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
@ -163,16 +164,6 @@
<Operation>0</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
@ -183,12 +174,6 @@
<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>
@ -241,6 +226,16 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
@ -261,6 +256,66 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
@ -271,6 +326,16 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
@ -441,6 +506,56 @@
<Operation>1</Operation>
</Platform>
</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">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
@ -546,6 +661,130 @@
<Operation>0</Operation>
</Platform>
</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">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
@ -746,127 +985,6 @@
<Operation>1</Operation>
</Platform>
</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="Android64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
@ -879,6 +997,7 @@
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64x" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>

View File

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

View File

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

View File

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