Merge branch 'master' into feature_restclient

This commit is contained in:
João Antônio Duarte 2020-11-13 18:15:33 -03:00
commit b9bee3fb2a
4 changed files with 81 additions and 48 deletions

View File

@ -397,7 +397,7 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
- Fixed! [issue388](https://github.com/danieleteti/delphimvcframework/issues/388) - Fixed! [issue388](https://github.com/danieleteti/delphimvcframework/issues/388)
- Fixed! Has been patched a serious security bug affecting deployment configurations which uses internal WebServer to serve static files (do not affect all Apache, IIS or proxied deployments). Thanks to **Stephan Munz** to have discovered it. *Update to dmvcframework-3.2-RC5+ is required for all such kind of deployments.* - Fixed! Has been patched a serious security bug affecting deployment configurations which uses internal WebServer to serve static files (do not affect all Apache, IIS or proxied deployments). Thanks to **Stephan Munz** to have discovered it. *Update to dmvcframework-3.2-RC5+ is required for all such kind of deployments.*
## 3.2.1-carbon ("repo" version currently in beta) ## 3.2.1-carbon ("repo" version currently in RC phase)
### Improvements and Bug Fixes ### Improvements and Bug Fixes
@ -590,6 +590,8 @@ Congratulations to Daniele Teti and all the staff for the excellent work!" -- Ma
- Fix for [issue221](https://github.com/danieleteti/delphimvcframework/issues/221) - Fix for [issue221](https://github.com/danieleteti/delphimvcframework/issues/221)
- Fix for [issue430](https://github.com/danieleteti/delphimvcframework/issues/430) (Thanks to [sonjli](https://github.com/sonjli) for its initial work)
- Support for [Mustache](https://mustache.github.io/) partials (Thanks to [David Moorhouse](https://github.com/fastbike) and his work about [issue 221](https://github.com/danieleteti/delphimvcframework/issues/221)). Sample *\samples\serversideviews_mustache* has been updated to show how to use partials. - Support for [Mustache](https://mustache.github.io/) partials (Thanks to [David Moorhouse](https://github.com/fastbike) and his work about [issue 221](https://github.com/danieleteti/delphimvcframework/issues/221)). Sample *\samples\serversideviews_mustache* has been updated to show how to use partials.
- Added dynamic properties access to `TMVCActiveRecord` descendants. Indexed property `Attributes` is index using the property name and set/get a `TValue` representing the property value. - Added dynamic properties access to `TMVCActiveRecord` descendants. Indexed property `Attributes` is index using the property name and set/get a `TValue` representing the property value.

View File

@ -10,30 +10,40 @@ uses
type type
TArticleProcessor = class(TInterfacedObject, IMVCEntityProcessor) TArticleProcessor = class(TInterfacedObject, IMVCEntityProcessor)
public public
procedure CreateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure CreateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string;
var Handled: Boolean); var Handled: Boolean);
procedure GetEntities(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure GetEntities(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string;
var Handled: Boolean);
procedure GetEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
procedure UpdateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
procedure DeleteEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean); var Handled: Boolean);
procedure GetEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
procedure UpdateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
procedure DeleteEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
end; end;
TContactProcessor = class(TInterfacedObject, IMVCEntityProcessor) TContactProcessor = class(TInterfacedObject, IMVCEntityProcessor)
public public
procedure CreateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure CreateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string;
var Handled: Boolean); var Handled: Boolean);
procedure GetEntities(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure GetEntities(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string;
var Handled: Boolean);
procedure GetEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
procedure UpdateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
procedure DeleteEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean); var Handled: Boolean);
procedure GetEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
procedure UpdateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
procedure DeleteEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
const id: Integer; var Handled: Boolean);
end; end;
implementation implementation
@ -47,10 +57,10 @@ uses
JsonDataObjects, JsonDataObjects,
MVCFramework.Serializer.Commons, MVCFramework.Serializer.Commons,
System.Generics.Collections, System.Generics.Collections,
MVCFramework.DuckTyping; MVCFramework.DuckTyping, MVCFramework.Commons, System.NetEncoding;
procedure TArticleProcessor.CreateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure TArticleProcessor.CreateEntity(const Context: TWebContext;
var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean);
var var
lArticle: TArticle; lArticle: TArticle;
begin begin
@ -64,26 +74,37 @@ begin
Handled := True; Handled := True;
end; end;
procedure TArticleProcessor.DeleteEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure TArticleProcessor.DeleteEntity(const Context: TWebContext;
const id: Integer; var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
begin
Handled := False;
end;
procedure TArticleProcessor.GetEntities(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string;
var Handled: Boolean); var Handled: Boolean);
begin begin
Handled := False; Handled := False;
end; end;
procedure TArticleProcessor.GetEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure TArticleProcessor.GetEntities(const Context: TWebContext;
const id: Integer; var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean);
begin
Handled := True;
Renderer.Render(ObjectDict().Add('data', TMVCActiveRecord.All<TArticle>,
procedure(const AObject: TObject; const Links: IMVCLinks)
begin
Links.AddRefLink
.Add(HATEOAS.HREF, 'https://www.google.com/search?q=' + TNetEncoding.URL.EncodeQuery(TArticle(AObject).Description))
.Add(HATEOAS._TYPE, 'text/html')
.Add(HATEOAS.REL, 'googlesearch');
end));
end;
procedure TArticleProcessor.GetEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
begin begin
Handled := False; Handled := False;
end; end;
procedure TArticleProcessor.UpdateEntity(const Context: TWebContext; const Renderer: TMVCRenderer; const entityname: string; procedure TArticleProcessor.UpdateEntity(const Context: TWebContext;
const id: Integer; var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean);
begin begin
Handled := False; Handled := False;
end; end;
@ -91,7 +112,7 @@ end;
{ TPeopleProcessor } { TPeopleProcessor }
procedure TContactProcessor.CreateEntity(const Context: TWebContext; procedure TContactProcessor.CreateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean);
var var
lSer: TMVCJsonDataObjectsSerializer; lSer: TMVCJsonDataObjectsSerializer;
lJSON: TJsonObject; lJSON: TJsonObject;
@ -111,12 +132,14 @@ begin
lPerson := TPerson.Create; lPerson := TPerson.Create;
try try
// deserialize person // deserialize person
lSer.JsonObjectToObject(lJSON, lPerson, TMVCSerializationType.stDefault, nil); lSer.JsonObjectToObject(lJSON, lPerson,
TMVCSerializationType.stDefault, nil);
lPhones := TObjectList<TPhone>.Create(True); lPhones := TObjectList<TPhone>.Create(True);
try try
// deserialize phones // deserialize phones
lSer.JsonArrayToList(lJSON.A['phones'], WrapAsList(lPhones), TPhone, TMVCSerializationType.stDefault, nil); lSer.JsonArrayToList(lJSON.A['phones'], WrapAsList(lPhones), TPhone,
TMVCSerializationType.stDefault, nil);
// persist to database using transaction // persist to database using transaction
TMVCActiveRecord.CurrentConnection.StartTransaction; TMVCActiveRecord.CurrentConnection.StartTransaction;
@ -146,26 +169,27 @@ begin
finally finally
lSer.Free; lSer.Free;
end; end;
Context.Response.CustomHeaders.Values['X-REF'] := Context.Request.PathInfo + '/' + lID.ToString; Context.Response.CustomHeaders.Values['X-REF'] := Context.Request.PathInfo +
'/' + lID.ToString;
Renderer.Render(TMVCResponse.Create(201, 'Contact created with phones', '')); Renderer.Render(TMVCResponse.Create(201, 'Contact created with phones', ''));
end; end;
procedure TContactProcessor.DeleteEntity(const Context: TWebContext; procedure TContactProcessor.DeleteEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer; const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean); var Handled: Boolean);
begin begin
Handled := False; // inherit the default behaviour Handled := False; // inherit the default behaviour
end; end;
procedure TContactProcessor.GetEntities(const Context: TWebContext; procedure TContactProcessor.GetEntities(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean); const Renderer: TMVCRenderer; const entityname: string; var Handled: Boolean);
begin begin
Handled := False; // inherit the default behaviour Handled := False; // inherit the default behaviour
end; end;
procedure TContactProcessor.GetEntity(const Context: TWebContext; procedure TContactProcessor.GetEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer; const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean); var Handled: Boolean);
var var
lContact: TContact; lContact: TContact;
lSer: TMVCJsonDataObjectsSerializer; lSer: TMVCJsonDataObjectsSerializer;
@ -182,8 +206,10 @@ begin
try try
lJSON := TJsonObject.Create; lJSON := TJsonObject.Create;
try try
lSer.ObjectToJsonObject(lContact, lJSON, TMVCSerializationType.stDefault, nil); lSer.ObjectToJsonObject(lContact, lJSON,
lSer.ListToJsonArray(WrapAsList(lPhones), lJSON.A['phones'], TMVCSerializationType.stDefault, nil); TMVCSerializationType.stDefault, nil);
lSer.ListToJsonArray(WrapAsList(lPhones), lJSON.A['phones'],
TMVCSerializationType.stDefault, nil);
Renderer.Render(lJSON, False); Renderer.Render(lJSON, False);
finally finally
lJSON.Free; lJSON.Free;
@ -201,16 +227,18 @@ begin
end; end;
procedure TContactProcessor.UpdateEntity(const Context: TWebContext; procedure TContactProcessor.UpdateEntity(const Context: TWebContext;
const Renderer: TMVCRenderer; const entityname: string; const id: Integer; const Renderer: TMVCRenderer; const entityname: string; const id: Integer;
var Handled: Boolean); var Handled: Boolean);
begin begin
Handled := False; // inherit the default behaviour Handled := False; // inherit the default behaviour
end; end;
initialization initialization
ActiveRecordMappingRegistry.AddEntityProcessor('articles', TArticleProcessor.Create); ActiveRecordMappingRegistry.AddEntityProcessor('articles',
ActiveRecordMappingRegistry.AddEntityProcessor('contacts', TContactProcessor.Create); TArticleProcessor.Create);
ActiveRecordMappingRegistry.AddEntityProcessor('contacts',
TContactProcessor.Create);
finalization finalization

View File

@ -31,7 +31,7 @@ end;
destructor TCommonService.Destroy; destructor TCommonService.Destroy;
begin begin
LogI('destroing ' + ClassName); LogI('destroying ' + ClassName);
inherited; inherited;
end; end;

View File

@ -504,6 +504,7 @@ var
lObj: TObject; lObj: TObject;
lJSONValue: TJsonBaseObject; lJSONValue: TJsonBaseObject;
lJsonDataType: TJsonDataType; lJsonDataType: TJsonDataType;
lLinks: IMVCLinks;
begin begin
Result := nil; Result := nil;
try try
@ -569,7 +570,9 @@ begin
begin begin
Result := TJsonObject.Create; Result := TJsonObject.Create;
AJsonDataType := jdtObject; AJsonDataType := jdtObject;
ObjectToJsonObject(AObject, TJsonObject(Result), GetSerializationType(AObject, AType), AIgnoredAttributes); lLinks := TMVCLinks.Create;
InternalObjectToJsonObject(AObject, TJsonObject(Result), GetSerializationType(AObject, AType), AIgnoredAttributes,
ASerializationAction, lLinks, nil);
end; end;
end; end;
except except