mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
Filrets (WIP) - refactored exception handling separating Controller exceptions from Protocol exceptions
This commit is contained in:
parent
4b89647ecc
commit
4e380e6ebd
@ -390,48 +390,18 @@ type
|
||||
end;
|
||||
|
||||
EMVCSessionExpiredException = class(EMVCException)
|
||||
private
|
||||
{ private declarations }
|
||||
protected
|
||||
{ protected declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
EMVCConfigException = class(EMVCException)
|
||||
private
|
||||
{ private declarations }
|
||||
protected
|
||||
{ protected declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
EMVCFrameworkViewException = class(EMVCException)
|
||||
private
|
||||
{ private declarations }
|
||||
protected
|
||||
{ protected declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
EMVCJWTException = class(EMVCException)
|
||||
private
|
||||
{ private declarations }
|
||||
protected
|
||||
{ protected declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
EMVCViewError = class(EMVCException)
|
||||
private
|
||||
{ private declarations }
|
||||
protected
|
||||
{ protected declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
TMVCStringDictionaryList = class;
|
||||
|
@ -52,15 +52,14 @@ procedure TMVCActionControllerFilter.DoFilter(
|
||||
const Context: TWebContext;
|
||||
const Router: IMVCRouter);
|
||||
var
|
||||
lSelectedController: TMVCController;
|
||||
lControllerInstance: TMVCController;
|
||||
lBodyParameter: TObject;
|
||||
lActionFormalParams: TArray<TRttiParameter>;
|
||||
lActualParams: TArray<TValue>;
|
||||
lRouterMethodToCallName: string;
|
||||
lHandled: Boolean;
|
||||
begin
|
||||
try
|
||||
lSelectedController := Router.CreateControllerInstance;
|
||||
lControllerInstance := Router.CreateControllerInstance;
|
||||
except
|
||||
on Ex: Exception do
|
||||
begin
|
||||
@ -70,51 +69,75 @@ begin
|
||||
raise EMVCException.Create(http_status.InternalServerError, 'Cannot create controller');
|
||||
end;
|
||||
end;
|
||||
|
||||
TWebContextHack(Context).fActionQualifiedName := Router.ActionQualifiedName;
|
||||
lSelectedController.Engine := Self.GetEngine;
|
||||
TMVCControllerHack(lSelectedController).Context := Context;
|
||||
lBodyParameter := nil;
|
||||
TMVCControllerHack(lSelectedController).MVCControllerAfterCreate;
|
||||
try
|
||||
TMVCControllerHack(lSelectedController).ContentType :=
|
||||
BuildContentType(Router.ResponseContentMediaType, Router.ResponseContentCharSet);
|
||||
lActionFormalParams := Router.ActionMethod.GetParameters;
|
||||
if (Length(lActionFormalParams) = 0) then
|
||||
SetLength(lActualParams, 0)
|
||||
else if (Length(lActionFormalParams) = 1) and
|
||||
(SameText(lActionFormalParams[0].ParamType.QualifiedName, 'MVCFramework.TWebContext')) then
|
||||
begin
|
||||
SetLength(lActualParams, 1);
|
||||
lActualParams[0] := Context;
|
||||
end
|
||||
else
|
||||
begin
|
||||
FillActualParamsForAction(lSelectedController, Context, lActionFormalParams, lRouterMethodToCallName,
|
||||
lActualParams, lBodyParameter);
|
||||
end;
|
||||
TMVCControllerHack(lSelectedController).OnBeforeAction(Context, lRouterMethodToCallName, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
try
|
||||
Router.ActionMethod.Invoke(lSelectedController, lActualParams);
|
||||
finally
|
||||
TMVCControllerHack(lSelectedController).OnAfterAction(Context, lRouterMethodToCallName);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
TWebContextHack(Context).FActionQualifiedName := Router.ActionQualifiedName;
|
||||
lControllerInstance.Engine := Self.GetEngine;
|
||||
TMVCControllerHack(lControllerInstance).Context := Context;
|
||||
lBodyParameter := nil;
|
||||
TMVCControllerHack(lControllerInstance).MVCControllerAfterCreate;
|
||||
try
|
||||
lBodyParameter.Free;
|
||||
except
|
||||
on E: Exception do
|
||||
TMVCControllerHack(lControllerInstance).ContentType :=
|
||||
BuildContentType(Router.ResponseContentMediaType, Router.ResponseContentCharSet);
|
||||
lActionFormalParams := Router.ActionMethod.GetParameters;
|
||||
if (Length(lActionFormalParams) = 0) then
|
||||
SetLength(lActualParams, 0)
|
||||
else if (Length(lActionFormalParams) = 1) and
|
||||
(SameText(lActionFormalParams[0].ParamType.QualifiedName, 'MVCFramework.TWebContext')) then
|
||||
begin
|
||||
LogE(Format('Cannot free Body object: [CLS: %s][MSG: %s]', [E.Classname, E.Message]));
|
||||
SetLength(lActualParams, 1);
|
||||
lActualParams[0] := Context;
|
||||
end
|
||||
else
|
||||
begin
|
||||
FillActualParamsForAction(lControllerInstance, Context, lActionFormalParams,
|
||||
Router.ActionMethod.Name,
|
||||
lActualParams, lBodyParameter);
|
||||
end;
|
||||
TMVCControllerHack(lControllerInstance).OnBeforeAction(Context, Router.ActionMethod.Name, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
try
|
||||
try
|
||||
Router.ActionMethod.Invoke(lControllerInstance, lActualParams);
|
||||
Context.Response.ContentType := TMVCControllerHack(lControllerInstance).ContentType;
|
||||
finally
|
||||
TMVCControllerHack(lControllerInstance).OnAfterAction(Context, Router.ActionMethod.Name);
|
||||
end;
|
||||
except
|
||||
on E: EMVCException do
|
||||
begin
|
||||
if not GetEngine.CustomExceptionHandling(E, lControllerInstance, Context) then
|
||||
begin
|
||||
Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
[E.Classname, E.Message, GetRequestShortDescription(Context.Request.RawWebRequest), E.DetailedMessage], LOGGERPRO_TAG);
|
||||
if Assigned(lControllerInstance) then
|
||||
begin
|
||||
lControllerInstance.ResponseStatus(E.HTTPErrorCode);
|
||||
lControllerInstance.Render(E);
|
||||
end
|
||||
else
|
||||
begin
|
||||
GetEngine.SendRawHTTPStatus(Context, E.HTTPErrorCode, Format('[%s] %s', [E.Classname, E.Message]), E.Classname);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
try
|
||||
lBodyParameter.Free;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
LogE(Format('Cannot free Body object: [CLS: %s][MSG: %s]', [E.Classname, E.Message]));
|
||||
end;
|
||||
end;
|
||||
TMVCControllerHack(lControllerInstance).MVCControllerBeforeDestroy;
|
||||
end;
|
||||
TMVCControllerHack(lSelectedController).MVCControllerBeforeDestroy;
|
||||
// fOnRouterLog(lRouter, rlsRouteFound, lContext);
|
||||
finally
|
||||
lControllerInstance.Free;
|
||||
end;
|
||||
Context.Response.ContentType := TMVCControllerHack(lSelectedController).ContentType;
|
||||
// fOnRouterLog(lRouter, rlsRouteFound, lContext);
|
||||
end;
|
||||
|
||||
procedure TMVCActionControllerFilter.FillActualParamsForAction(
|
||||
|
@ -148,53 +148,53 @@ begin
|
||||
end;
|
||||
end; // end-execute-routing
|
||||
except
|
||||
on ESess: EMVCSessionExpiredException do
|
||||
begin
|
||||
if not fEngine.CustomExceptionHandling(ESess, lSelectedController, Context) then
|
||||
begin
|
||||
Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
[ESess.Classname, ESess.Message, GetRequestShortDescription(Context.Request.RawWebRequest), ESess.DetailedMessage],
|
||||
LOGGERPRO_TAG);
|
||||
Context.SessionStop;
|
||||
lSelectedController.ResponseStatus(ESess.HTTPErrorCode);
|
||||
lSelectedController.Render(ESess);
|
||||
end;
|
||||
end;
|
||||
on E: EMVCException do
|
||||
begin
|
||||
if not fEngine.CustomExceptionHandling(E, lSelectedController, Context) then
|
||||
begin
|
||||
Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
[E.Classname, E.Message, GetRequestShortDescription(Context.Request.RawWebRequest), E.DetailedMessage], LOGGERPRO_TAG);
|
||||
if Assigned(lSelectedController) then
|
||||
begin
|
||||
lSelectedController.ResponseStatus(E.HTTPErrorCode);
|
||||
lSelectedController.Render(E);
|
||||
end
|
||||
else
|
||||
begin
|
||||
fEngine.SendRawHTTPStatus(Context, E.HTTPErrorCode, Format('[%s] %s', [E.Classname, E.Message]), E.Classname);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
on EIO: EInvalidOp do
|
||||
begin
|
||||
if not fEngine.CustomExceptionHandling(EIO, lSelectedController, Context) then
|
||||
begin
|
||||
Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
[EIO.Classname, EIO.Message, GetRequestShortDescription(Context.Request.RawWebRequest), 'Invalid Op'], LOGGERPRO_TAG);
|
||||
if Assigned(lSelectedController) then
|
||||
begin
|
||||
lSelectedController.ResponseStatus(http_status.InternalServerError);
|
||||
lSelectedController.Render(EIO);
|
||||
end
|
||||
else
|
||||
begin
|
||||
fEngine.SendRawHTTPStatus(Context, http_status.InternalServerError,
|
||||
Format('[%s] %s', [EIO.Classname, EIO.Message]), EIO.Classname);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// on ESess: EMVCSessionExpiredException do
|
||||
// begin
|
||||
// if not fEngine.CustomExceptionHandling(ESess, lSelectedController, Context) then
|
||||
// begin
|
||||
// Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
// [ESess.Classname, ESess.Message, GetRequestShortDescription(Context.Request.RawWebRequest), ESess.DetailedMessage],
|
||||
// LOGGERPRO_TAG);
|
||||
// Context.SessionStop;
|
||||
// lSelectedController.ResponseStatus(ESess.HTTPErrorCode);
|
||||
// lSelectedController.Render(ESess);
|
||||
// end;
|
||||
// end;
|
||||
// on E: EMVCException do
|
||||
// begin
|
||||
// if not fEngine.CustomExceptionHandling(E, lSelectedController, Context) then
|
||||
// begin
|
||||
// Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
// [E.Classname, E.Message, GetRequestShortDescription(Context.Request.RawWebRequest), E.DetailedMessage], LOGGERPRO_TAG);
|
||||
// if Assigned(lSelectedController) then
|
||||
// begin
|
||||
// lSelectedController.ResponseStatus(E.HTTPErrorCode);
|
||||
// lSelectedController.Render(E);
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// fEngine.SendRawHTTPStatus(Context, E.HTTPErrorCode, Format('[%s] %s', [E.Classname, E.Message]), E.Classname);
|
||||
// end;
|
||||
// end;
|
||||
// end;
|
||||
// on EIO: EInvalidOp do
|
||||
// begin
|
||||
// if not fEngine.CustomExceptionHandling(EIO, lSelectedController, Context) then
|
||||
// begin
|
||||
// Log.Error('[%s] %s [PathInfo "%s"] (Custom message: "%s")',
|
||||
// [EIO.Classname, EIO.Message, GetRequestShortDescription(Context.Request.RawWebRequest), 'Invalid Op'], LOGGERPRO_TAG);
|
||||
// if Assigned(lSelectedController) then
|
||||
// begin
|
||||
// lSelectedController.ResponseStatus(http_status.InternalServerError);
|
||||
// lSelectedController.Render(EIO);
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// fEngine.SendRawHTTPStatus(Context, http_status.InternalServerError,
|
||||
// Format('[%s] %s', [EIO.Classname, EIO.Message]), EIO.Classname);
|
||||
// end;
|
||||
// end;
|
||||
// end;
|
||||
on Ex: Exception do
|
||||
begin
|
||||
if not fEngine.CustomExceptionHandling(Ex, lSelectedController, Context) then
|
||||
|
@ -526,7 +526,7 @@ type
|
||||
FLoggedUser: TUser;
|
||||
FWebSession: TWebSession;
|
||||
FData: TMVCStringDictionary;
|
||||
fIntfObject: IInterface;
|
||||
FIntfObject: IInterface;
|
||||
function GetWebSession: TWebSession;
|
||||
function GetLoggedUser: TUser;
|
||||
function GetParamsTable: TMVCRequestParamsTable;
|
||||
@ -535,7 +535,7 @@ type
|
||||
function GetIntfObject: IInterface;
|
||||
procedure SetIntfObject(const Value: IInterface);
|
||||
protected
|
||||
fActionQualifiedName: String;
|
||||
FActionQualifiedName: String;
|
||||
procedure Flush; virtual;
|
||||
procedure BindToSession(const ASessionId: string);
|
||||
function SendSessionCookie(const AContext: TWebContext): string;
|
||||
@ -578,11 +578,8 @@ type
|
||||
TMVCBase = class
|
||||
private
|
||||
FEngine: TMVCEngine;
|
||||
FApplicationSession: TWebApplicationSession;
|
||||
function GetEngine: TMVCEngine;
|
||||
function GetConfig: TMVCConfig;
|
||||
function GetApplicationSession: TWebApplicationSession;
|
||||
procedure SetApplicationSession(const AValue: TWebApplicationSession);
|
||||
procedure SetEngine(const AValue: TMVCEngine);
|
||||
protected
|
||||
class function GetApplicationFileName: string; static;
|
||||
@ -590,8 +587,6 @@ type
|
||||
public
|
||||
property Engine: TMVCEngine read GetEngine write SetEngine;
|
||||
property Config: TMVCConfig read GetConfig;
|
||||
property ApplicationSession: TWebApplicationSession read GetApplicationSession
|
||||
write SetApplicationSession;
|
||||
end;
|
||||
|
||||
TMVCResponse = class;
|
||||
@ -2922,14 +2917,6 @@ begin
|
||||
Result := IncludeTrailingPathDelimiter(ExtractFilePath(GetApplicationFileName));
|
||||
end;
|
||||
|
||||
function TMVCBase.GetApplicationSession: TWebApplicationSession;
|
||||
begin
|
||||
if not Assigned(FApplicationSession) then
|
||||
raise EMVCException.CreateFmt('ApplicationSession not assigned to this %s instance.',
|
||||
[Classname]);
|
||||
Result := FApplicationSession;
|
||||
end;
|
||||
|
||||
function TMVCBase.GetConfig: TMVCConfig;
|
||||
begin
|
||||
Result := Engine.Config;
|
||||
@ -2942,11 +2929,6 @@ begin
|
||||
Result := FEngine;
|
||||
end;
|
||||
|
||||
procedure TMVCBase.SetApplicationSession(const AValue: TWebApplicationSession);
|
||||
begin
|
||||
FApplicationSession := AValue;
|
||||
end;
|
||||
|
||||
procedure TMVCBase.SetEngine(const AValue: TMVCEngine);
|
||||
begin
|
||||
FEngine := AValue;
|
||||
@ -3698,36 +3680,6 @@ begin
|
||||
if (GetContext.Response.StatusCode = http_status.OK) then
|
||||
ResponseStatus(http_status.InternalServerError, AException.Message + ' [' +
|
||||
AException.Classname + ']');
|
||||
|
||||
// if (not GetContext.Request.IsAjax) and (GetContext.Request.ClientPrefer(TMVCMediaType.TEXT_HTML)) then
|
||||
// begin
|
||||
// SetContentType(TMVCMediaType.TEXT_HTML);
|
||||
// Render(AException, False);
|
||||
// exit;
|
||||
// ResponseStream.Clear;
|
||||
// ResponseStream.Append
|
||||
// ('<html><head><style>pre { padding: 15px; color: #000000; background-color: #e0e0e0; }</style></head><body>')
|
||||
// .Append('<h1>' + Config[TMVCConfigKey.ServerName] + ': Error Raised</h1>')
|
||||
// .AppendFormat('<pre>HTTP Return Code: %d' + sLineBreak,
|
||||
// [GetContext.Response.StatusCode]).AppendFormat('HTTP Reason Text: "%s"</pre>',
|
||||
// [GetContext.Response.ReasonString])
|
||||
// .Append('<h3><pre>').AppendFormat('Exception Class Name : %s' + sLineBreak, [AException.Classname])
|
||||
// .AppendFormat('Exception Message : %s' + sLineBreak, [AException.Message]).Append('</pre></h3>');
|
||||
// if Assigned(AExceptionItems) and (AExceptionItems.Count > 0) then
|
||||
// begin
|
||||
// ResponseStream.Append('<h2><pre>');
|
||||
// for S in AExceptionItems do
|
||||
// ResponseStream.AppendLine('- ' + S);
|
||||
// ResponseStream.Append('</pre><h2>');
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// ResponseStream.AppendLine('<pre>No other information available</pre>');
|
||||
// end;
|
||||
// ResponseStream.Append('</body></html>');
|
||||
// RenderResponseStream;
|
||||
// end
|
||||
// else
|
||||
begin
|
||||
R := TMVCErrorResponse.Create;
|
||||
try
|
||||
|
@ -1,2 +1,2 @@
|
||||
const
|
||||
DMVCFRAMEWORK_VERSION = '3.4.0-neon-beta';
|
||||
DMVCFRAMEWORK_VERSION = 'x.x.x-feature-filters';
|
@ -24,7 +24,9 @@ uses
|
||||
MVCFramework.Tests.Serializer.Entities in '..\..\common\MVCFramework.Tests.Serializer.Entities.pas',
|
||||
FDConnectionConfigU in '..\..\common\FDConnectionConfigU.pas',
|
||||
Entities in '..\Several\Entities.pas',
|
||||
EntitiesProcessors in '..\Several\EntitiesProcessors.pas';
|
||||
EntitiesProcessors in '..\Several\EntitiesProcessors.pas',
|
||||
MVCFramework.Filters.Action in '..\..\..\sources\MVCFramework.Filters.Action.pas',
|
||||
MVCFramework.Filters.Router in '..\..\..\sources\MVCFramework.Filters.Router.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
@ -141,6 +141,8 @@
|
||||
<DCCReference Include="..\..\common\FDConnectionConfigU.pas"/>
|
||||
<DCCReference Include="..\Several\Entities.pas"/>
|
||||
<DCCReference Include="..\Several\EntitiesProcessors.pas"/>
|
||||
<DCCReference Include="..\..\..\sources\MVCFramework.Filters.Action.pas"/>
|
||||
<DCCReference Include="..\..\..\sources\MVCFramework.Filters.Router.pas"/>
|
||||
<BuildConfiguration Include="Base">
|
||||
<Key>Base</Key>
|
||||
</BuildConfiguration>
|
||||
|
Loading…
Reference in New Issue
Block a user