#1 2017-08-28 12:43:49

vlad
Member
Registered: 2017-03-20
Posts: 16

TCollection and Error Code 406

Hello,

I keep getting error code 406 exception when trying to publish a TInterfacedCollection property to TSQLRecord class that in turn is a parameter to a function of an interface. I also tried TObjectList with TJSONSerializer.RegisterClassForJSON instead of TCollection, but with the same result. In example below if I remove Sprites property from TSQLImage, everything works properly.

Could you please help me understand what I'm doing wrong?

  TSprite = class(TCollectionItem)
  published
    property ImageID: integer read fImageID write fImageID;
    property Name: string read fName write fName;
    property Left: integer read fLeft write fLeft;
    property Top: integer read fTop write fTop;
    property Height: integer read fHeight write fHeight;
    property Width: integer read fWidth write fWidth;
    property FlipHorz: boolean read fFlipHorz write fFlipHorz;
    property FlipVert: boolean read fFlipVert write fFlipVert;
    property Scale: integer read fScale write fScale;
    property Visible: boolean read fVisible write fVisible;
  end;

  TSpriteList = class(TInterfacedCollection)
  private
    function GetCollItem(aIndex: Integer): TSprite;
  protected
    class function GetClass: TCollectionItemClass; override;
  public
    function Add: TSprite;
    property Item[aIndex: Integer]: TSprite read GetCollItem; default;
  end;

  TSQLImage = class(TSQLRecord)
  published
    property Name: string index 30 read fName write fName stored AS_UNIQUE;
    property Image: TSQLRawBlob read fImage write fImage;
    property Sprites: TSpriteList read fSprites;
  end;

  IQBImageService = interface(IInvokable)
    ['{26D32153-FAE3-4CDE-AB32-C5A6A334015B}']
    function Save(const aItem: TSQLImage; const Data: TServiceCustomAnswer; out ID: TID): RawUTF8;
  end;

-------------------------------------
    gs_rec := TSQLImage.Create;
    gs_rec.Name := 'test';
    cu.Header := BINARY_CONTENT_TYPE_HEADER;
    cu.Content := '';

    if aClient.Services.Resolve(IQBImageService, I) = true then
    begin
      st_err := I.Save(gs_rec, cu, ID);
    end;
-------------------------------------

First chance exception at $76D3B802. Exception class EInterfaceFactoryException with message
'TInterfacedObjectFakeClient.FakeCall(IQBImageService.Save) failed: '{
"errorCode":406,
"errorText":"sicShared execution failed (probably due to bad input parameters) for QBImageService.Save"
}''.
Process QB.exe (10816)

Offline

#2 2017-08-28 12:50:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: TCollection and Error Code 406

Your use of TServiceCustomAnswer is incorrect: if you want to let the binary data retrieved from the server without any JSON serialization, you need to have a single function with no output parameter, but the result function as TServiceCustomAnswer. For additional output parameters, you could manually append the other values to the returned binary, then parse it on the client side.

But here, you expect the input to be sent from the client to the server, so you should use not TServiceCustomAnswer (which is for Answers, as its name states), but e.g. a RawByteString value.
Note that it will be base-64 encoded... so perhaps here a method-based service, with raw direct body access, may be more efficient than an interface-based service, for your Save method.

Offline

#3 2017-08-28 13:24:24

vlad
Member
Registered: 2017-03-20
Posts: 16

Re: TCollection and Error Code 406

Thanks Arnaud. For now I'll stick to interface-based service in order not to change things much. I replaced TServiceCustomAnswer input parameter with RawByteString:

function Save(const aItem: TSQLImage; const Data: RawByteString; out ID: TID): RawUTF8;

However, I'm still getting 406 exception. This happens only when I add Sprites property to TSQLImage class in example above.

Offline

#4 2017-08-28 15:16:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: TCollection and Error Code 406

I'm not sure that TInterfacedCollection is handled as property of TSQLRecord.
TInterfacedCollection is to be used as parameter for SOA calls, not as field for ORM properties.

You may consider using T*ObjArray instead.

Offline

#5 2017-09-01 19:23:48

vlad
Member
Registered: 2017-03-20
Posts: 16

Re: TCollection and Error Code 406

T*ObjArray works, thank you.

Offline

Board footer

Powered by FluxBB