Passing extra information with response

I want to pass extra information besides the response structure in service method. e.g if the service method returns list of Customer then depending on some condition I would like to pass extra guid to the client. How can I do this?

I have looked at envelopes but I am not sure whether they will do what I want, so I want to ask a question before I go and implement custom envelope.

Your server can return NewStruct or NewStruct1 depending on some condition instead of list of Customer like:

  NewStruct = class(TROComplexType)
..
    property aList:NewArray;
  end;

  NewStruct1 = class(NewStruct)
..
    property aGuid:Guid;
  end;

  INewService = interface
..
    function NewMethod: NewStruct;
  end;

on client side:

  a := lService.NewMethod;
  if a is NewStruct1 then begin
     ...
  end;

I should have been more precise, I need to pass extra information which could be errors or work log back to the client, but it is optional. The solution should be able to work with all the server methods, which are 100+ now. That is the reason I was thinking of using envelopes. If using envelopes is the correct solution could you please provide some example code.

yes, this is correct solution. in your case, you should have active envelope on server side and inactive on client side.
in this case, client will be able to decode data passed by server and will not pass anything to server.

simple example:

type
  TMyEnvelope = class(TROMessageEnvelope)
  private
    fData: String;
  protected
    procedure intProcessOutgoing(Source, Dest: TStream; aMessage: IROMessage); override;
    procedure intProcessIncoming(Source, Dest: TStream; aMessage: IROMessage); override;
    function GetDefaultEnvelopeMarker: string; override;
  published
    property ExtraData: String read fData write fData;
  end;

{ TMyEnvelope }

function TMyEnvelope.GetDefaultEnvelopeMarker: string;
begin
  Result := 'ExtraData';
end;

procedure TMyEnvelope.intProcessIncoming(Source, Dest: TStream;
  aMessage: IROMessage);
var
  len: integer;
begin
  Source.Read(len, Sizeof(Integer));
  if len > 0 then begin
    SetLength(fData, len div sizeof(Char));
    Source.Read(Pointer(@fData)^, len);
  end
  else
    len := 0;
  Dest.CopyFrom(Source, Source.Size - Source.Position);
end;

procedure TMyEnvelope.intProcessOutgoing(Source, Dest: TStream;
  aMessage: IROMessage);
var
  len: integer;
begin
  len := Length(fData)*SizeOf(Char);
  Dest.Write(len, Sizeof(Integer));
  if len > 0 then
    Dest.Write(Pointer(@fData)^, len);
  Dest.CopyFrom(Source, Source.Size);
end;

My Delphi code is

unit V6LinkEnvelope;

interface

uses
  {$IFDEF DELPHIXE2UP}
    System.SysUtils, System.Classes,
  {$ELSE}
    SysUtils, Classes,
  {$ENDIF}
  uROMessage, uROClientIntf;

type
  Tv6LinkEnvelope = class(TROMessageEnvelope)
  private
    FData: string;
  protected
    procedure intProcessIncoming(Source: TStream; Dest: TStream;
      aMessage: IROMessage); override;
    procedure intProcessOutgoing(Source: TStream; Dest: TStream;
      aMessage: IROMessage); override;
    function GetDefaultEnvelopeMarker: string; override;
  end;

implementation

{ Tv6LinkEnvelope }

function Tv6LinkEnvelope.GetDefaultEnvelopeMarker: string;
begin
  Result := 'V6LinkEnvelope';
end;

procedure Tv6LinkEnvelope.intProcessIncoming(Source, Dest: TStream;
  aMessage: IROMessage);
var
  iLen: integer;
begin
  Source.Read(iLen, Sizeof(Integer));
  if iLen > 0 then begin
    SetLength(FData, iLen div sizeof(Char));
    Source.Read(Pointer(@FData)^, iLen);
  end
  else
    iLen := 0;
  Dest.CopyFrom(Source, Source.Size - Source.Position);
end;

procedure Tv6LinkEnvelope.intProcessOutgoing(Source, Dest: TStream;
  aMessage: IROMessage);
var
  iLen: integer;
begin
  FData := 'Hello World How Are You';
  iLen := Length(FData) * SizeOf(Char);
  Dest.Write(iLen, Sizeof(Integer));
  if iLen > 0 then
    Dest.Write(Pointer(@FData)^, iLen);
  Dest.CopyFrom(Source, Source.Size);
end;

end.

and C# code is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using RemObjects.SDK.Helpers;

namespace Softtech.V6API
{
    public class V6LinkEnvelope : RemObjects.SDK.MessageEnvelope
    {
        public override string DefaultEnvelopeMarker
        {
            get { return "V6LinkEnvelope"; }
        }

        protected override MemoryStream InternalUnwrap(Stream source)
        {
            var dest = new MemoryStream();
            var reader = new BinaryReader(source);
            var dataSize = reader.ReadInt32();
            var data = reader.ReadBytes(dataSize);
            string dataString = System.Text.Encoding.UTF8.GetString(data);
            source.CopyTo(dest);
            return dest;
        }

        protected override MemoryStream InternalWrap(Stream source, byte[] header)
        {
            return source as MemoryStream;
        }
    }
}

It is working but I do not get the FData string set in Delphi in “dataString” variable in C#. Could you please have a look?

Hello

You cannot decode Delphi-sent string as UTF8. Depending on Delphi version you need to use either System.Text.Encoding.ASCII or System.Text.Encoding.Unicode to decode incoming bytes.

Regards