Fixed a mleak in caso of disconnection while the request is running (https://github.com/danieleteti/delphimvcframework/issues/323)

This commit is contained in:
Daniele Teti 2020-01-24 10:09:14 +01:00
parent 9d7ff23c11
commit 3233ea123f
11 changed files with 72 additions and 29 deletions

View File

@ -41,12 +41,12 @@ type
[MVCDoc('Creates a new article and returns "201: Created"')] [MVCDoc('Creates a new article and returns "201: Created"')]
[MVCPath] [MVCPath]
[MVCHTTPMethod([httpPOST])] [MVCHTTPMethod([httpPOST])]
procedure CreateArticle(Context: TWebContext); procedure CreateArticle;
[MVCDoc('Creates new articles from a list and returns "201: Created"')] [MVCDoc('Creates new articles from a list and returns "201: Created"')]
[MVCPath('/bulk')] [MVCPath('/bulk')]
[MVCHTTPMethod([httpPOST])] [MVCHTTPMethod([httpPOST])]
procedure CreateArticles(Context: TWebContext); procedure CreateArticles;
end; end;
implementation implementation
@ -58,22 +58,22 @@ uses
BusinessObjects, BusinessObjects,
Commons, Commons,
mvcframework.Serializer.Intf, mvcframework.Serializer.Intf,
System.Generics.Collections; System.Generics.Collections, System.SysUtils;
procedure TArticlesController.CreateArticle(Context: TWebContext); procedure TArticlesController.CreateArticle;
var var
Article: TArticle; Article: TArticle;
begin begin
Article := Context.Request.BodyAs<TArticle>; Article := Context.Request.BodyAs<TArticle>;
try try
GetArticlesService.Add(Article); GetArticlesService.Add(Article);
Render(201, 'Article Created'); ResponseCreated('/articles/' + Article.ID.ToString, 'Article Created');
finally finally
Article.Free; Article.Free;
end; end;
end; end;
procedure TArticlesController.CreateArticles(Context: TWebContext); procedure TArticlesController.CreateArticles;
var var
lArticles: TObjectList<TArticle>; lArticles: TObjectList<TArticle>;
lArticle: TArticle; lArticle: TArticle;

View File

@ -18,6 +18,14 @@ type
end; end;
[MVCPath('/private')]
TPrivateController = class(TBaseController)
public
[MVCPath('/articles')]
[MVCHTTPMethods([httpDELETE])]
procedure DeleteAllArticles;
end;
implementation implementation
uses uses
@ -46,4 +54,11 @@ begin
Result := FDM; Result := FDM;
end; end;
{ TPrivateController }
procedure TPrivateController.DeleteAllArticles;
begin
GetArticlesService.DeleteAllArticles();
end;
end. end.

View File

@ -27,6 +27,7 @@ type
function GetArticles(const aTextSearch: String): TObjectList<TArticle>; function GetArticles(const aTextSearch: String): TObjectList<TArticle>;
function GetByID(const AID: Integer): TArticle; function GetByID(const AID: Integer): TArticle;
procedure Delete(AArticolo: TArticle); procedure Delete(AArticolo: TArticle);
procedure DeleteAllArticles;
procedure Add(AArticolo: TArticle); procedure Add(AArticolo: TArticle);
procedure Update(AArticolo: TArticle); procedure Update(AArticolo: TArticle);
end; end;
@ -64,6 +65,11 @@ begin
Cmd.Execute; Cmd.Execute;
end; end;
procedure TArticlesService.DeleteAllArticles;
begin
FDM.Connection.ExecSQL('delete from articoli');
end;
function TArticlesService.GetAll: TObjectList<TArticle>; function TArticlesService.GetAll: TObjectList<TArticle>;
begin begin
FDM.dsArticles.Open('SELECT * FROM ARTICOLI ORDER BY ID', []); FDM.dsArticles.Open('SELECT * FROM ARTICOLI ORDER BY ID', []);

View File

@ -20,7 +20,8 @@ implementation
{ %CLASSGROUP 'Vcl.Controls.TControl' } { %CLASSGROUP 'Vcl.Controls.TControl' }
uses Controllers.Articles, MVCFramework.Middleware.CORS, MVCFramework.Middleware.Compression; uses Controllers.Articles, MVCFramework.Middleware.CORS, MVCFramework.Middleware.Compression,
Controllers.Base;
{$R *.dfm} {$R *.dfm}
@ -28,6 +29,9 @@ procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin begin
FEngine := TMVCEngine.Create(self); FEngine := TMVCEngine.Create(self);
FEngine.AddController(TArticlesController); FEngine.AddController(TArticlesController);
{$IFDEF TESTINSTANCE}
FEngine.AddController(TPrivateController);
{$ENDIF}
FEngine.AddMiddleware(TCORSMiddleware.Create); FEngine.AddMiddleware(TCORSMiddleware.Create);
FEngine.AddMiddleware(TMVCCompressionMiddleware.Create(256)); FEngine.AddMiddleware(TMVCCompressionMiddleware.Create(256));

View File

@ -68,7 +68,7 @@
<DCC_UsePackage>FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapServer;DataSnapCommon;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;soaprtl;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;VclSmp;FireDACMSSQLDriver;FireDAC;DBXInformixDriver;Intraweb;VCLRESTComponents;DataSnapConnectors;DataSnapServerMidas;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;FireDACMSAccDriver;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage> <DCC_UsePackage>FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapServer;DataSnapCommon;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;IndyIPCommon;CloudService;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;soaprtl;FMXTee;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;VclSmp;FireDACMSSQLDriver;FireDAC;DBXInformixDriver;Intraweb;VCLRESTComponents;DataSnapConnectors;DataSnapServerMidas;dsnapcon;DBXFirebirdDriver;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;FireDACMSAccDriver;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''"> <PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define> <DCC_Define>DEBUG;TESTINSTANCE;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs> <DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize> <DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames> <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
@ -153,10 +153,10 @@
<Source Name="MainSource">articles_crud.dpr</Source> <Source Name="MainSource">articles_crud.dpr</Source>
</Source> </Source>
<Excluded_Packages> <Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k240.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages> <Excluded_Packages Name="$(BDSBIN)\bcboffice2k260.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)\bcbofficexp260.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)\dcloffice2k260.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)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="3"> <Deployment Version="3">

View File

@ -41,6 +41,10 @@ type
protected protected
procedure OnBeforeAction(AContext: TWebContext; const AActionName: string; var AHandled: Boolean); override; procedure OnBeforeAction(AContext: TWebContext; const AActionName: string; var AHandled: Boolean); override;
public public
[MVCHTTPMethod([httpGET])]
[MVCPath('/customers/withcallback')]
procedure GetCustomersWithCallback;
[MVCHTTPMethod([httpGET])] [MVCHTTPMethod([httpGET])]
[MVCPath('/customers/($ID)')] [MVCPath('/customers/($ID)')]
[MVCProduces('text/plain')] [MVCProduces('text/plain')]
@ -54,10 +58,6 @@ type
[MVCPath('/customers')] [MVCPath('/customers')]
procedure GetCustomersAsDataSetWithRefLinks; procedure GetCustomersAsDataSetWithRefLinks;
[MVCHTTPMethod([httpGET])]
[MVCPath('/customers/withcallback')]
procedure GetCustomersWithCallback;
[MVCHTTPMethod([httpGET])] [MVCHTTPMethod([httpGET])]
[MVCPath('/customers/($ID)/asdataset')] [MVCPath('/customers/($ID)/asdataset')]
procedure GetCustomer_AsDataSetRecord(const ID: Integer); procedure GetCustomer_AsDataSetRecord(const ID: Integer);

View File

@ -1506,7 +1506,11 @@ destructor TMVCWebResponse.Destroy;
begin begin
if FFlushOnDestroy then if FFlushOnDestroy then
begin begin
Flush; try
Flush;
except
//do nothing
end;
end; end;
inherited Destroy; inherited Destroy;
end; end;
@ -1744,11 +1748,23 @@ end;
destructor TWebContext.Destroy; destructor TWebContext.Destroy;
begin begin
FResponse.Free; try
FRequest.Free; FResponse.Free;
FData.Free; except
if Assigned(FLoggedUser) then end;
FLoggedUser.Free; try
FRequest.Free;
except
end;
try
FData.Free;
except
end;
try
if Assigned(FLoggedUser) then
FLoggedUser.Free;
except
end;
inherited Destroy; inherited Destroy;
end; end;
@ -2093,21 +2109,24 @@ begin
LActionFormalParams := LRouter.MethodToCall.GetParameters; LActionFormalParams := LRouter.MethodToCall.GetParameters;
if (Length(LActionFormalParams) = 0) then if (Length(LActionFormalParams) = 0) then
SetLength(LActualParams, 0) SetLength(LActualParams, 0)
else else if (Length(LActionFormalParams) = 1) and
if (Length(LActionFormalParams) = 1) and
(SameText(LActionFormalParams[0].ParamType.QualifiedName, 'MVCFramework.TWebContext')) then (SameText(LActionFormalParams[0].ParamType.QualifiedName, 'MVCFramework.TWebContext')) then
begin begin
SetLength(LActualParams, 1); SetLength(LActualParams, 1);
LActualParams[0] := LContext; LActualParams[0] := LContext;
end end
else else
begin
try try
FillActualParamsForAction(LContext, LActionFormalParams, LRouter.MethodToCall.Name, FillActualParamsForAction(LContext, LActionFormalParams, LRouter.MethodToCall.Name,
LActualParams); LActualParams);
Except except
on e:Exception do on E: Exception do
SendRawHTTPStatus(Lcontext, HTTP_STATUS.BadRequest, e.Message, e.ClassName); begin
SendRawHTTPStatus(LContext, HTTP_STATUS.BadRequest, e.Message, e.ClassName);
end;
end; end;
end;
LSelectedController.OnBeforeAction(LContext, LRouter.MethodToCall.Name, LHandled); LSelectedController.OnBeforeAction(LContext, LRouter.MethodToCall.Name, LHandled);

View File

@ -1,2 +1,2 @@
const const
DMVCFRAMEWORK_VERSION = '3.2.0 (boron) RC3'; DMVCFRAMEWORK_VERSION = '3.2.0 (boron) RC4';

View File

@ -192,7 +192,6 @@
<DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.Entities.pas"/> <DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.Entities.pas"/>
<DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.EntitiesModule.pas"> <DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.EntitiesModule.pas">
<Form>EntitiesModule</Form> <Form>EntitiesModule</Form>
<FormType>dfm</FormType>
<DesignClass>TDataModule</DesignClass> <DesignClass>TDataModule</DesignClass>
</DCCReference> </DCCReference>
<DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.Intf.pas"/> <DCCReference Include="..\..\common\MVCFramework.Tests.Serializer.Intf.pas"/>