mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
Added SWAGGER support also for APIs generated by the TMVCActiveRecordController
This commit is contained in:
parent
082089f9a1
commit
613347be1f
@ -710,6 +710,8 @@ type
|
||||
class function CreateMVCActiveRecord<T: TMVCActiveRecord>(AQualifiedClassName: string; const AParams: TArray<TValue> = nil): T;
|
||||
end;
|
||||
|
||||
TMVCEntityMapping = TPair<String, TMVCActiveRecordClass>;
|
||||
|
||||
IMVCEntitiesRegistry = interface
|
||||
['{BB227BEB-A74A-4637-8897-B13BA938C07B}']
|
||||
procedure AddEntity(const aURLSegment: string; const aActiveRecordClass: TMVCActiveRecordClass);
|
||||
@ -721,6 +723,7 @@ type
|
||||
out aMVCEntityProcessor: IMVCEntityProcessor)
|
||||
: Boolean;
|
||||
function GetEntities: TArray<String>;
|
||||
function GetURLSegmentWithEntities: TArray<TMVCEntityMapping>;
|
||||
end;
|
||||
|
||||
TMVCEntitiesRegistry = class(TInterfacedObject, IMVCEntitiesRegistry)
|
||||
@ -738,6 +741,7 @@ type
|
||||
function FindProcessorByURLSegment(const aURLSegment: string; out aMVCEntityProcessor: IMVCEntityProcessor)
|
||||
: Boolean;
|
||||
function GetEntities: TArray<String>;
|
||||
function GetURLSegmentWithEntities: TArray<TMVCEntityMapping>;
|
||||
end;
|
||||
|
||||
IMVCActiveRecordTableMap = interface
|
||||
@ -3785,6 +3789,20 @@ begin
|
||||
Result := fEntitiesDict.Keys.ToArray;
|
||||
end;
|
||||
|
||||
function TMVCEntitiesRegistry.GetURLSegmentWithEntities: TArray<TMVCEntityMapping>;
|
||||
var
|
||||
lPair: TMVCEntityMapping;
|
||||
i: Integer;
|
||||
begin
|
||||
SetLength(Result, fEntitiesDict.Count);
|
||||
i := 0;
|
||||
for lPair in fEntitiesDict do
|
||||
begin
|
||||
Result[I] := lPair;
|
||||
Inc(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ EMVCActiveRecord }
|
||||
|
||||
constructor EMVCActiveRecord.Create(const AMsg: string);
|
||||
|
@ -37,7 +37,7 @@ uses
|
||||
FireDAC.Comp.Client,
|
||||
MVCFramework.RQL.Parser,
|
||||
System.Generics.Collections,
|
||||
MVCFramework.Serializer.Commons;
|
||||
MVCFramework.Serializer.Commons, MVCFramework.Swagger.Commons;
|
||||
|
||||
type
|
||||
{$SCOPEDENUMS ON}
|
||||
@ -57,28 +57,64 @@ type
|
||||
const aURLSegment: String = ''); reintroduce; overload;
|
||||
destructor Destroy; override;
|
||||
|
||||
function GetURLSegment: String;
|
||||
|
||||
[MVCPath('/($entityname)')]
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Retrieve a list of {singularmodel}', 'Get{pluralmodel}')]
|
||||
[MVCSwagResponses(HTTP_STATUS.OK, 'List of {singularmodel}', SWAGUseDefaultControllerModel, True)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
[MVCSwagParam(TMVCSwagParamLocation.plQuery, 'rql', 'RQL filter used to filter the list of {singularmodel}', SWAGUseDefaultControllerModel, TMVCSwagParamType.ptString, False)]
|
||||
procedure GetEntities(const entityname: string); virtual;
|
||||
|
||||
[MVCPath('/($entityname)/searches')]
|
||||
[MVCHTTPMethod([httpGET, httpPOST])]
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Searches through {pluralmodel} and returns a list of {singularmodel}', 'Get{pluralmodel}BySearch')]
|
||||
[MVCSwagResponses(HTTP_STATUS.OK, 'List of {singularmodel}', SWAGUseDefaultControllerModel, True)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
[MVCSwagParam(TMVCSwagParamLocation.plQuery, 'rql', 'RQL filter used to filter the list of {singularmodel}', SWAGUseDefaultControllerModel, TMVCSwagParamType.ptString, False)]
|
||||
procedure GetEntitiesByRQL(const entityname: string); virtual;
|
||||
|
||||
[MVCPath('/($entityname)/searches')]
|
||||
[MVCHTTPMethod([httpPOST])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Searches through {pluralmodel} and returns a list of {singularmodel}', 'Get{pluralmodel}BySearchAsPOST')]
|
||||
[MVCSwagResponses(HTTP_STATUS.OK, 'List of {singularmodel}', SWAGUseDefaultControllerModel, True)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
[MVCSwagParam(TMVCSwagParamLocation.plQuery, 'rql', 'RQL filter used to filter the list of {singularmodel}', SWAGUseDefaultControllerModel, TMVCSwagParamType.ptString, False)]
|
||||
procedure GetEntitiesByRQLwithPOST(const entityname: string); virtual;
|
||||
|
||||
[MVCPath('/($entityname)/($id)')]
|
||||
[MVCHTTPMethod([httpGET])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Gets a {singularmodel} entity or 404 not found', 'Get{singularmodel}ByID')]
|
||||
[MVCSwagResponses(HTTP_STATUS.OK, 'One {singularmodel}', SWAGUseDefaultControllerModel)]
|
||||
[MVCSwagResponses(HTTP_STATUS.NotFound, 'Error', TMVCErrorResponse)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
procedure GetEntity(const entityname: string; const id: Integer); virtual;
|
||||
|
||||
[MVCPath('/($entityname)')]
|
||||
[MVCHTTPMethod([httpPOST])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Creates a {singularmodel} and returns a new id', 'Create{singularmodel}')]
|
||||
[MVCSwagResponses(HTTP_STATUS.Created, 'One {singularmodel}', '')]
|
||||
[MVCSwagResponses(HTTP_STATUS.NotFound, 'Error', TMVCErrorResponse)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
[MVCSwagParam(TMVCSwagParamLocation.plBody, '{singularmodel}', 'A single entity of type {singularmodel}', SWAGUseDefaultControllerModel, TMVCSwagParamType.ptString, True)]
|
||||
procedure CreateEntity(const entityname: string); virtual;
|
||||
|
||||
[MVCPath('/($entityname)/($id)')]
|
||||
[MVCHTTPMethod([httpPUT])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Updates a {singularmodel} by id', 'Update{singularmodel}ByID')]
|
||||
[MVCSwagResponses(HTTP_STATUS.OK, 'One {singularmodel}', SWAGUseDefaultControllerModel)]
|
||||
[MVCSwagResponses(HTTP_STATUS.NotFound, 'Error', TMVCErrorResponse)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
[MVCSwagParam(TMVCSwagParamLocation.plBody, '{singularmodel}', 'A single entity of type {singularmodel}', SWAGUseDefaultControllerModel, TMVCSwagParamType.ptString, True)]
|
||||
procedure UpdateEntity(const entityname: string; const id: Integer); virtual;
|
||||
|
||||
[MVCPath('/($entityname)/($id)')]
|
||||
[MVCHTTPMethod([httpDELETE])]
|
||||
[MVCSwagSummary(TSwaggerConst.USE_DEFAULT_SUMMARY_TAGS, 'Deletes a {singularmodel} by id', 'Delete{singularmodel}ByID')]
|
||||
[MVCSwagResponses(HTTP_STATUS.NoContent, '')]
|
||||
[MVCSwagResponses(HTTP_STATUS.NotFound, 'Error', TMVCErrorResponse)]
|
||||
[MVCSwagResponses(HTTP_STATUS.BadRequest, '', TMVCErrorResponse)]
|
||||
procedure DeleteEntity(const entityname: string; const id: Integer); virtual;
|
||||
|
||||
end;
|
||||
@ -184,30 +220,33 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMVCActiveRecordController.GetEntitiesByRQL(const entityname: string);
|
||||
begin
|
||||
GetEntities(entityname);
|
||||
end;
|
||||
|
||||
procedure TMVCActiveRecordController.GetEntitiesByRQLwithPOST(const entityname: string);
|
||||
var
|
||||
lRQL: string;
|
||||
lJSON: TJsonObject;
|
||||
begin
|
||||
if Context.Request.HTTPMethod = httpPOST then
|
||||
begin
|
||||
lJSON := TJsonObject.Parse(Context.Request.Body) as TJsonObject;
|
||||
try
|
||||
if Assigned(lJSON) then
|
||||
begin
|
||||
lRQL := lJSON.s['rql'];
|
||||
end
|
||||
else
|
||||
begin
|
||||
lRQL := '';
|
||||
end;
|
||||
finally
|
||||
lJSON.Free;
|
||||
lJSON := TJsonObject.Parse(Context.Request.Body) as TJsonObject;
|
||||
try
|
||||
if Assigned(lJSON) then
|
||||
begin
|
||||
lRQL := lJSON.s['rql'];
|
||||
end
|
||||
else
|
||||
begin
|
||||
lRQL := '';
|
||||
end;
|
||||
Context.Request.QueryStringParams.Values['rql'] := lRQL;
|
||||
finally
|
||||
lJSON.Free;
|
||||
end;
|
||||
Context.Request.QueryStringParams.Values['rql'] := lRQL;
|
||||
GetEntities(entityname);
|
||||
end;
|
||||
|
||||
|
||||
procedure TMVCActiveRecordController.GetEntity(const entityname: string; const id: Integer);
|
||||
var
|
||||
lAR: TMVCActiveRecord;
|
||||
@ -264,6 +303,11 @@ begin
|
||||
Result := StrToIntDef(Config[TMVCConfigKey.MaxEntitiesRecordCount], 20);
|
||||
end;
|
||||
|
||||
function TMVCActiveRecordController.GetURLSegment: String;
|
||||
begin
|
||||
Result := fURLSegment;
|
||||
end;
|
||||
|
||||
function TMVCActiveRecordController.CheckAuthorization(aClass: TMVCActiveRecordClass;
|
||||
aAction: TMVCActiveRecordAction): Boolean;
|
||||
begin
|
||||
|
@ -57,6 +57,7 @@ type
|
||||
procedure DocumentApiSettings(AContext: TWebContext; ASwagDoc: TSwagDoc);
|
||||
procedure DocumentApiAuthentication(const ASwagDoc: TSwagDoc);
|
||||
procedure DocumentApi(ASwagDoc: TSwagDoc);
|
||||
procedure DocumentActiveRecordControllerApi(ASwagDoc: TSwagDoc);
|
||||
procedure SortApiPaths(ASwagDoc: TSwagDoc);
|
||||
procedure InternalRender(AContent: string; AContext: TWebContext);
|
||||
public
|
||||
@ -92,14 +93,17 @@ uses
|
||||
Swag.Doc.Path.Operation,
|
||||
Swag.Doc.Path.Operation.Response,
|
||||
MVCFramework.Middleware.JWT,
|
||||
MVCFramework.ActiveRecordController,
|
||||
Swag.Doc.Path.Operation.RequestParameter,
|
||||
Swag.Doc.SecurityDefinitionApiKey,
|
||||
Swag.Doc.SecurityDefinitionBasic,
|
||||
Swag.Doc.Definition,
|
||||
System.Generics.Collections,
|
||||
System.Generics.Defaults,
|
||||
System.Generics.Defaults,
|
||||
System.TypInfo,
|
||||
Json.Common.Helpers;
|
||||
MVCFramework.Serializer.Commons,
|
||||
Json.Common.Helpers,
|
||||
MVCFramework.ActiveRecord;
|
||||
|
||||
{ TMVCSwaggerMiddleware }
|
||||
|
||||
@ -127,6 +131,166 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMVCSwaggerMiddleware.DocumentActiveRecordControllerApi(ASwagDoc: TSwagDoc);
|
||||
var
|
||||
lRttiContext: TRttiContext;
|
||||
lObjType: TRttiType;
|
||||
lController: TMVCControllerDelegate;
|
||||
lSwagPath: TSwagPath;
|
||||
lAttr: TCustomAttribute;
|
||||
lControllerPath: string;
|
||||
lMethodPath: string;
|
||||
lMethod: TRttiMethod;
|
||||
lFoundAttr: Boolean;
|
||||
lMVCHttpMethods: TMVCHTTPMethods;
|
||||
lSwagPathOp: TSwagPathOperation;
|
||||
I: TMVCHTTPMethodType;
|
||||
lPathUri: string;
|
||||
lIndex: Integer;
|
||||
lAuthTypeName: string;
|
||||
lIsIgnoredPath: Boolean;
|
||||
lControllerDefaultModelClass: TClass;
|
||||
lControllerDefaultSummaryTags: TArray<string>;
|
||||
lPathAttributeFound: Boolean;
|
||||
lVisitedMethodSignatures: TList<String>;
|
||||
lMethodSignature: string;
|
||||
lControllerDefaultModelSingularName: string;
|
||||
lControllerDefaultModelPluralName: string;
|
||||
lEntitiesMapping: TArray<TMVCEntityMapping>;
|
||||
lPrefixURLSegment: string;
|
||||
lEntityMapping: TMVCEntityMapping;
|
||||
begin
|
||||
lVisitedMethodSignatures := TList<String>.Create;
|
||||
try
|
||||
lRttiContext := TRttiContext.Create;
|
||||
try
|
||||
for lController in fEngine.Controllers do
|
||||
begin
|
||||
lControllerPath := '';
|
||||
SetLength(lControllerDefaultSummaryTags, 0);
|
||||
lPathAttributeFound := False;
|
||||
lObjType := lRttiContext.GetType(lController.Clazz);
|
||||
|
||||
//Automatic API generated by TMVCActiveRecordController
|
||||
if not lController.Clazz.InheritsFrom(TMVCActiveRecordController) then
|
||||
begin
|
||||
Continue;
|
||||
end;
|
||||
|
||||
lEntitiesMapping := ActiveRecordMappingRegistry.GetURLSegmentWithEntities;
|
||||
lPrefixURLSegment := lController.URLSegment;
|
||||
|
||||
for lEntityMapping in lEntitiesMapping do
|
||||
begin
|
||||
lControllerPath := lPrefixURLSegment;
|
||||
lControllerDefaultModelClass := lEntityMapping.Value;
|
||||
lControllerDefaultModelSingularName := lEntityMapping.Value.ClassName;
|
||||
lControllerDefaultModelPluralName := lEntityMapping.Key;
|
||||
SetLength(lControllerDefaultSummaryTags, 1);
|
||||
lControllerDefaultSummaryTags[0] := TMVCSerializerHelper.ApplyNameCase(ncPascalCase, lEntityMapping.Key);
|
||||
|
||||
for lMethod in lObjType.GetMethods do
|
||||
begin
|
||||
{only public and published methods are inspected}
|
||||
if not (lMethod.Visibility in [mvPublished, mvPublic]) then
|
||||
begin
|
||||
Continue;
|
||||
end;
|
||||
|
||||
lIsIgnoredPath := False;
|
||||
lFoundAttr := False;
|
||||
lMVCHttpMethods := [];
|
||||
lMethodPath := '';
|
||||
|
||||
for lAttr in lMethod.GetAttributes do
|
||||
begin
|
||||
if lAttr is MVCSwagIgnorePathAttribute then
|
||||
begin
|
||||
lIsIgnoredPath := True;
|
||||
end;
|
||||
if lAttr is MVCPathAttribute then
|
||||
begin
|
||||
lMethodPath := MVCPathAttribute(lAttr).Path;
|
||||
lMethodPath := lMethodPath.Replace('($entityname)', lEntityMapping.Key, [rfReplaceAll]);
|
||||
lFoundAttr := True;
|
||||
end;
|
||||
if lAttr is MVCHTTPMethodsAttribute then
|
||||
begin
|
||||
lMVCHttpMethods := MVCHTTPMethodsAttribute(lAttr).MVCHTTPMethods;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (not lIsIgnoredPath) and lFoundAttr then
|
||||
begin
|
||||
lMethodSignature := lObjType.Name + '.' + lEntityMapping.Key + '_' + lMethod.Name;
|
||||
if lVisitedMethodSignatures.Contains(lMethodSignature) then
|
||||
begin
|
||||
Continue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
lVisitedMethodSignatures.Add(lMethodSignature);
|
||||
end;
|
||||
|
||||
//LogI(lObjType.Name + '.' + lMethod.Name + ' ' + lMethod.Parent.ToString);
|
||||
lSwagPath := nil;
|
||||
lPathUri := TMVCSwagger.MVCPathToSwagPath(lControllerPath + lMethodPath);
|
||||
for lIndex := 0 to Pred(ASwagDoc.Paths.Count) do
|
||||
begin
|
||||
if SameText(ASwagDoc.Paths[lIndex].Uri, lPathUri) then
|
||||
begin
|
||||
lSwagPath := ASwagDoc.Paths[lIndex];
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
if not Assigned(lSwagPath) then
|
||||
begin
|
||||
lSwagPath := TSwagPath.Create;
|
||||
lSwagPath.Uri := lPathUri;
|
||||
ASwagDoc.Paths.Add(lSwagPath);
|
||||
end;
|
||||
|
||||
for I in lMVCHttpMethods do
|
||||
begin
|
||||
lSwagPathOp := TSwagPathOperation.Create;
|
||||
TMVCSwagger.FillOperationSummary(
|
||||
lSwagPathOp,
|
||||
lMethod,
|
||||
ASwagDoc.Definitions,
|
||||
I,
|
||||
lControllerDefaultModelClass,
|
||||
lControllerDefaultModelSingularName,
|
||||
lControllerDefaultModelPluralName,
|
||||
lControllerDefaultSummaryTags);
|
||||
if TMVCSwagger.MethodRequiresAuthentication(lMethod, lObjType, lAuthTypeName) then
|
||||
begin
|
||||
lSwagPathOp.Security.Add(lAuthTypeName);
|
||||
end;
|
||||
lSwagPathOp.Parameters.AddRange(
|
||||
TMVCSwagger.GetParamsFromMethod(
|
||||
lSwagPath.Uri,
|
||||
lMethod,
|
||||
ASwagDoc.Definitions,
|
||||
lControllerDefaultModelClass,
|
||||
lControllerDefaultModelSingularName,
|
||||
lControllerDefaultModelPluralName)
|
||||
);
|
||||
lSwagPathOp.Operation := TMVCSwagger.MVCHttpMethodToSwagPathOperation(I);
|
||||
lSwagPath.Operations.Add(lSwagPathOp);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
lRttiContext.Free;
|
||||
end;
|
||||
finally
|
||||
lVisitedMethodSignatures.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMVCSwaggerMiddleware.DocumentApi(ASwagDoc: TSwagDoc);
|
||||
var
|
||||
lRttiContext: TRttiContext;
|
||||
@ -462,6 +626,7 @@ begin
|
||||
DocumentApiInfo(LSwagDoc);
|
||||
DocumentApiSettings(AContext, LSwagDoc);
|
||||
DocumentApiAuthentication(LSwagDoc);
|
||||
DocumentActiveRecordControllerApi(LSwagDoc);
|
||||
DocumentApi(LSwagDoc);
|
||||
SortApiPaths(LSwagDoc);
|
||||
|
||||
|
@ -921,7 +921,11 @@ begin
|
||||
|
||||
lSwagResponse := TSwagResponse.Create;
|
||||
lSwagResponse.StatusCode := lSwagResponsesAttr.StatusCode.ToString;
|
||||
lSwagResponse.Description := lSwagResponsesAttr.Description;
|
||||
//lSwagResponse.Description := lSwagResponsesAttr.Description;
|
||||
lSwagResponse.Description := ApplyModelName(
|
||||
lSwagResponsesAttr.Description,
|
||||
aControllerDefaultModelSingularName,
|
||||
aControllerDefaultModelPluralName);
|
||||
if not lSwagResponsesAttr.JsonSchema.IsEmpty then
|
||||
begin
|
||||
lSwagResponse.Schema.JsonSchema := TJSONObject.ParseJSONValue(lSwagResponsesAttr.JsonSchema) as TJSONObject
|
||||
|
@ -771,6 +771,10 @@ type
|
||||
function BadRequestResponse: IMVCResponse; overload;
|
||||
function BadRequestResponse(const Message: String): IMVCResponse; overload;
|
||||
|
||||
function UnprocessableContentResponse(const Error: TObject): IMVCResponse; overload;
|
||||
function UnprocessableContentResponse: IMVCResponse; overload;
|
||||
function UnprocessableContentResponse(const Message: String): IMVCResponse; overload;
|
||||
|
||||
function CreatedResponse(const Location: string = ''; const Body: TObject = nil): IMVCResponse; overload;
|
||||
function CreatedResponse(const Location: string; const Message: String): IMVCResponse; overload;
|
||||
|
||||
@ -4023,11 +4027,6 @@ begin
|
||||
'Hint: Messaging extensions require a valid clientid. Did you call /messages/clients/YOUR_CLIENT_ID ?');
|
||||
end;
|
||||
|
||||
function TMVCRenderer.BadRequestResponse: IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.BadRequest, nil);
|
||||
end;
|
||||
|
||||
function TMVCRenderer.AcceptedResponse(const Location: string;
|
||||
const Body: TObject): IMVCResponse;
|
||||
var
|
||||
@ -4045,6 +4044,11 @@ begin
|
||||
Result := lRespBuilder.StatusCode(HTTP_STATUS.Accepted).Build;
|
||||
end;
|
||||
|
||||
function TMVCRenderer.BadRequestResponse: IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.BadRequest, nil);
|
||||
end;
|
||||
|
||||
function TMVCRenderer.BadRequestResponse(const Error: TObject): IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.BadRequest, Error);
|
||||
@ -4055,6 +4059,22 @@ begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.BadRequest, nil, Message);
|
||||
end;
|
||||
|
||||
function TMVCRenderer.UnprocessableContentResponse: IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.UnprocessableEntity, nil);
|
||||
end;
|
||||
|
||||
function TMVCRenderer.UnprocessableContentResponse(const Error: TObject): IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.UnprocessableEntity, Error);
|
||||
end;
|
||||
|
||||
function TMVCRenderer.UnprocessableContentResponse(const Message: String): IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.UnprocessableEntity, nil, Message);
|
||||
end;
|
||||
|
||||
|
||||
function TMVCRenderer.ConflictResponse: IMVCResponse;
|
||||
begin
|
||||
Result := StatusCodeResponse(HTTP_STATUS.Conflict, nil);
|
||||
|
@ -1565,8 +1565,6 @@ var
|
||||
lFunc: TTProTemplateFunction;
|
||||
lAnonFunc: TTProTemplateAnonFunction;
|
||||
lIntegerPar1: Integer;
|
||||
lInt64Value: Int64;
|
||||
lExtendedValue: Double;
|
||||
begin
|
||||
aFunctionName := lowercase(aFunctionName);
|
||||
if SameText(aFunctionName, 'gt') then
|
||||
|
Loading…
Reference in New Issue
Block a user