OBJECT Table 76101 .NET Assembly
{
  OBJECT-PROPERTIES
  {
    Date=10.11.15;
    Time=[ 9:09:48];
    Modified=Yes;
    Version List=Vjeko.com.1.00;
  }
  PROPERTIES
  {
  }
  FIELDS
  {
    { 1   ;   ;Assembly Name       ;Text250       ;CaptionML=ENU=Assembly Name }
    { 2   ;   ;User ID             ;Code50        ;TableRelation=User."User Name";
                                                   OnValidate=VAR
                                                                UserMgt@1000 : Codeunit 418;
                                                              BEGIN
                                                                UserMgt.ValidateUserID("User ID");
                                                              END;

                                                   OnLookup=VAR
                                                              UserMgt@1000 : Codeunit 418;
                                                            BEGIN
                                                              UserMgt.LookupUserID("User ID");
                                                            END;

                                                   CaptionML=ENU=User ID }
    { 3   ;   ;Tier                ;Option        ;CaptionML=ENU=Tier;
                                                   OptionCaptionML=ENU=Both,Server,Client;
                                                   OptionString=Both,Server,Client }
    { 10  ;   ;Assembly            ;BLOB          ;CaptionML=ENU=Assembly }
  }
  KEYS
  {
    {    ;Assembly Name,User ID,Tier              ;Clustered=Yes }
  }
  FIELDGROUPS
  {
  }
  CODE
  {

    PROCEDURE InstallAssembly@3(VAR InStr@1000 : InStream;VAR Asm@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly";Name@1004 : Text);
    VAR
      Asmbl@1005 : Record 76101;
      MemStream@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.MemoryStream";
      OutStr@1003 : OutStream;
    BEGIN
      WITH Asmbl DO BEGIN
        MemStream := MemStream.MemoryStream();
        COPYSTREAM(MemStream,InStr);
        Asm := Asm.Load(MemStream.ToArray());

        IF Name = '' THEN BEGIN
          "Assembly Name" := Asm.FullName;
        END ELSE
          "Assembly Name" := Name;

        Assembly.CREATEOUTSTREAM(OutStr);
        MemStream.Seek(0,0);
        COPYSTREAM(OutStr,MemStream);

        IF NOT INSERT() THEN
          MODIFY();
      END;
    END;

    BEGIN
    END.
  }
}

OBJECT Codeunit 66001 Demo #1 - Codeunit
{
  OBJECT-PROPERTIES
  {
    Date=18.11.15;
    Time=22:41:26;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
    OnRun=BEGIN
          END;

  }
  CODE
  {
    VAR
      ControlAddIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn";

    PROCEDURE SetControlAddIn@2(ControlAddInIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn");
    BEGIN
      ControlAddIn := ControlAddInIn;
    END;

    PROCEDURE SayHello@3(Name@1000 : Text);
    BEGIN
      ControlAddIn.SayHello(Name);
    END;

    EVENT ControlAddIn@1000::ControlReady@1();
    BEGIN
    END;

    BEGIN
    END.
  }
}

OBJECT Codeunit 66002 Demo #1 - Codeunit (investig.)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=16:22:00;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
    OnRun=BEGIN
          END;

  }
  CODE
  {
    VAR
      ControlAddIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn";

    PROCEDURE SayHello@3(Name@1000 : Text);
    BEGIN
      ControlAddIn.SayHello(Name);
    END;

    PROCEDURE SetControlAddIn@2(ControlAddInIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn");
    BEGIN
      // The following assignment will work, but SayHello will fail
      ControlAddIn := ControlAddInIn;
    END;

    PROCEDURE SetControlAddInThatWorks@4(ControlAddInIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn");
    BEGIN
      // However, if I do this...
      ControlAddInIn.SayHello('Hello, World, from codeunit!');
      // ... this works...

      // ... but as soon as I assign it...
      ControlAddIn := ControlAddInIn;

      // ... it does not work anymore
      ControlAddIn.SayHello('Hello, World, it does not work!');
    END;

    PROCEDURE SetControlAddInAndInspectIt@1(ControlAddInIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn");
    VAR
      IEnumerable@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.Generic.IEnumerable`1";
      List@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Collections.Generic.List`1";
      Object@1003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object";
    BEGIN
      // Let's see who you are...
      MESSAGE('ControlAddInIn is %1, but is it null? %2.',GETDOTNETTYPE(ControlAddInIn),ISNULL(ControlAddInIn));

      // If it's not null, then it should be assignable to System.Object
      Object := ControlAddInIn;
      // ... and it apparently is.

      // So, let's see what's the runtime type of the object?
      MESSAGE('Runtime type of object is %1.',Object.GetType());

      // That's failing? Comment that line above, and let's see something...
      MESSAGE('Is this Object by any chance null? %1',ISNULL(Object));
    END;

    BEGIN
    END.
  }
}

OBJECT Codeunit 66011 Demo #2, #3 and #4 - Codeunit
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=10:19:47;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
    OnRun=BEGIN
          END;

  }
  CODE
  {
    VAR
      Marshaller@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Marshaller";

    PROCEDURE Initialize@2(MarshallerIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Marshaller");
    BEGIN
      Marshaller := MarshallerIn;
    END;

    PROCEDURE DoStuff@5();
    VAR
      Args@1001 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.StringRequest";
    BEGIN
      MESSAGE('I am doing my stuff...');
      IF CONFIRM('May I now call a page method?') THEN
        Marshaller.Marshal(Args.StringRequest('Hello, World!'));
    END;

    EVENT Marshaller@1000::MarshalledEvent@8(args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
    END;

    BEGIN
    END.
  }
}

OBJECT Codeunit 76101 Assembly Resolver
{
  OBJECT-PROPERTIES
  {
    Date=20.11.15;
    Time=10:50:40;
    Modified=Yes;
    Version List=Vjeko.com.1.00;
  }
  PROPERTIES
  {
    SingleInstance=Yes;
    OnRun=VAR
            Asm@1010 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly";
            AsmClient@1000 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly" RUNONCLIENT;
            Object@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object";
          BEGIN
            RetrieveResolverAssembly(Asm);
            Object := Asm.CreateInstance(TypeName);

            ResolveServerSide(AssemblyName,Object);
            ResolverNst := Object;

            IF IsWindowsClient() THEN BEGIN
              RetrieveResolverAssembly(AsmClient);
              ResolverRtc := AsmClient.CreateInstance(TypeName);
            END;

            ResolveAssemblies();
          END;

  }
  CODE
  {
    VAR
      ResolverNst@1000 : DotNet "'NavHelper.AssemblyResolver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.NavHelper.AssemblyResolver.Resolver" WITHEVENTS;
      ResolverRtc@1001 : DotNet "'NavHelper.AssemblyResolver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.NavHelper.AssemblyResolver.Resolver" RUNONCLIENT;
      CompilerError@1003 : TextConst 'ENU=Error compiling the resolver assembly:\\%1';
      AssemblyName@1004 : TextConst 'ENU="NavHelper.AssemblyResolver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"';
      TypeName@1005 : TextConst 'ENU=NavHelper.AssemblyResolver.AssemblyResolver';

    LOCAL PROCEDURE ResolveAssemblies@6();
    VAR
      Asmbl@1000 : Record 76101;
    BEGIN
      WITH Asmbl DO BEGIN
        SETFILTER("User ID",'%1|%2','',USERID);
        IF FINDSET() THEN
          REPEAT
            IF IsWindowsClient() AND (Tier IN [Tier::Both,Tier::Client]) THEN
              ResolveAssembly(Asmbl,ResolverRtc,Tier::Client);
            IF Tier IN [Tier::Both,Tier::Server] THEN
              ResolveAssembly(Asmbl,ResolverNst,Tier::Server);
          UNTIL NEXT = 0;
      END;
    END;

    LOCAL PROCEDURE ResolveServerSide@1(Name@1000 : Text;Resolver@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object");
    VAR
      Asmbl@1001 : Record 76101;
    BEGIN
      WITH Asmbl DO BEGIN
        SETRANGE("Assembly Name",Name);
        SETFILTER(Tier,'%1|%2',Tier::Both,Tier::Server);
        SETFILTER("User ID",'%1|%2','',USERID);
        IF FINDFIRST() THEN
          ResolveAssembly(Asmbl,Resolver,Tier::Server);
      END;
    END;

    LOCAL PROCEDURE ResolveAssembly@7(Asmbl@1000 : Record 76101;VAR Resolver@1007 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object";TargetTier@1003 : Integer);
    VAR
      Asm@1004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly";
      Bytes@1008 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array";
      MemStr@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.MemoryStream";
      MethodInfo@1005 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.MethodInfo";
      MethodInfoClient@1010 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.MethodInfo" RUNONCLIENT;
      Params@1006 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array";
      ParamsClient@1009 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array" RUNONCLIENT;
      Object@1011 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object";
      InStr@1001 : InStream;
    BEGIN
      LoadAssemblyBytes(Asmbl,Bytes);
      WITH Asmbl DO BEGIN
        CASE TargetTier OF
          Tier::Server:
            BEGIN
              MethodInfo := Resolver.GetType().GetMethod('ResolveAssembly');
              Params := Params.CreateInstance(GETDOTNETTYPE(Object),2);
              Params.SetValue("Assembly Name",0);
              Params.SetValue(Bytes,1);
              MethodInfo.Invoke(Resolver,Params);
            END;
          Tier::Client:
            BEGIN
              IF NOT IsWindowsClient() THEN
                EXIT;

              MethodInfoClient := Resolver.GetType().GetMethod('ResolveAssembly');
              ParamsClient := ParamsClient.CreateInstance(GETDOTNETTYPE(Object),2);
              ParamsClient.SetValue("Assembly Name",0);
              ParamsClient.SetValue(Bytes,1);
              MethodInfoClient.Invoke(Resolver,ParamsClient);
            END;
        END;
      END;
    END;

    LOCAL PROCEDURE IsWindowsClient@4() : Boolean;
    BEGIN
      EXIT(CURRENTCLIENTTYPE = CLIENTTYPE::Windows);
    END;

    LOCAL PROCEDURE LoadAssemblyBytes@65(Asmbl@1000 : Record 76101;VAR Bytes@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array");
    VAR
      MemStr@1004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.MemoryStream";
      InStr@1003 : InStream;
      Byte@1002 : Byte;
    BEGIN
      WITH Asmbl DO BEGIN
        CALCFIELDS(Assembly);
        Assembly.CREATEINSTREAM(InStr);
        MemStr := MemStr.MemoryStream();
        COPYSTREAM(MemStr,InStr);
        Bytes := MemStr.ToArray();
      END;
    END;

    LOCAL PROCEDURE CompileResolverAssembly@56(VAR Asm@1004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly");
    VAR
      CodeDomProvider@1003 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.CodeDom.Compiler.CodeDomProvider";
      CompilerParameters@1002 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.CodeDom.Compiler.CompilerParameters";
      CompilerResults@1001 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.CodeDom.Compiler.CompilerResults";
      Sources@1000 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array";
    BEGIN
      Sources := Sources.CreateInstance(GETDOTNETTYPE(''),1);
      Sources.SetValue(GetSource(),0);

      CodeDomProvider := CodeDomProvider.CreateProvider('CSharp');
      CompilerParameters := CompilerParameters.CompilerParameters();
      CompilerResults := CodeDomProvider.CompileAssemblyFromSource(CompilerParameters,Sources);
      IF CompilerResults.Errors.Count() > 0 THEN
        ERROR(CompilerError,CompilerResults.Errors.Item(0));

      InstallResolverAssembly(CompilerResults.PathToAssembly,Asm);
    END;

    LOCAL PROCEDURE InstallResolverAssembly@12(Path@1000 : Text;VAR Asm@1004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly");
    VAR
      Asmbl@1003 : Record 76101;
      AsmFile@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.File";
      MemStr@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.MemoryStream";
    BEGIN
      MemStr := MemStr.MemoryStream(AsmFile.ReadAllBytes(Path));
      Asmbl.InstallAssembly(MemStr,Asm,AssemblyName);
      ERASE(Path);
    END;

    LOCAL PROCEDURE RetrieveResolverAssembly@60(VAR Asm@1000 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly");
    VAR
      Asmbl@1001 : Record 76101;
      Bytes@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array";
    BEGIN
      Asmbl."Assembly Name" := AssemblyName;
      IF Asmbl.FIND() THEN BEGIN
        LoadAssemblyBytes(Asmbl,Bytes);
        Asm := Asm.Load(Bytes);
      END ELSE
        CompileResolverAssembly(Asm);
    END;

    LOCAL PROCEDURE GetSource@54() Source : Text;
    BEGIN
      Source := 'using System;using System.Collections.Generic;using System.Reflection;[assembly: AssemblyTitle("NavHelper';
      Source += '.AssemblyResolver")][assembly: AssemblyVersion("1.0.0.0")][assembly: AssemblyFileVersion("1.0.0.0")]names';
      Source += 'pace NavHelper.AssemblyResolver{public class Resolver{private readonly Dictionary<string,byte[]>_assembli';
      Source += 'es=new Dictionary<string,byte[]>();public event EventHandler<ResolveEventArgs>OnResolveAssembly;public vo';
      Source += 'id ResolveAssembly(string name,byte[] asm){if(_assemblies.ContainsKey(name))_assemblies.Remove(name);_ass';
      Source += 'emblies.Add(name,asm);}public Resolver(){AppDomain.CurrentDomain.AssemblyResolve+=(sender,args)=>{if(!_as';
      Source += 'semblies.ContainsKey(args.Name)&&OnResolveAssembly!=null)OnResolveAssembly.Invoke(sender,args);return _as';
      Source += 'semblies.ContainsKey(args.Name)?Assembly.Load(_assemblies[args.Name]):null;};}}}';
    END;

    EVENT ResolverNst@1000::OnResolveAssembly@10(sender@1001 : Variant;e@1000 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.ResolveEventArgs");
    BEGIN
      ResolveServerSide(e.Name,ResolverNst);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66001 Demo #1 - Page
{
  OBJECT-PROPERTIES
  {
    Date=18.11.15;
    Time=22:46:31;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      MyCodeunit@1000 : Codeunit 66001;

    EVENT ControlAddIn@-2::ControlReady@1();
    VAR
      ControlAddIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn";
    BEGIN
      MyCodeunit.SetControlAddIn(CurrPage.ControlAddIn);
      MyCodeunit.SayHello('Hello, World!');
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66002 Demo #1 - Page (no codeunit)
{
  OBJECT-PROPERTIES
  {
    Date=18.11.15;
    Time=22:59:01;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {

    EVENT ControlAddIn@-2::ControlReady@1();
    VAR
      ControlAddIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn";
    BEGIN
      CurrPage.ControlAddIn.SayHello('Hello, World!');
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66003 Demo #1 - Page (investigation)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=16:22:06;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      MyCodeunit@1000 : Codeunit 66002;

    EVENT ControlAddIn@-2::ControlReady@1();
    VAR
      ControlAddIn@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.IControlAddIn";
    BEGIN
      // What is CurrPage.ControlAddIn?
      //MESSAGE('CurrPage.ControlAddIn is %1',GETDOTNETTYPE(CurrPage.ControlAddIn));

      // Assignment passes nicely...
      ControlAddIn := CurrPage.ControlAddIn;
      //MESSAGE('ControlAddIn is %1',GETDOTNETTYPE(ControlAddIn));

      // ... but this fails:
      //ControlAddIn.SayHello('Hello, World!');

      // However, if you comment the line above, and then do this...
      //CurrPage.ControlAddIn.SayHello('Hello, World!');
      // ... of course, this works...

      // This - as you remember - will fail
      MyCodeunit.SetControlAddIn(CurrPage.ControlAddIn);
      //MyCodeunit.SayHello('Hello, World!');

      // However, if you comment those two lines, and do this...
      //MyCodeunit.SetControlAddInThatWorks(CurrPage.ControlAddIn);
      // ... it will work, then fail.

      // So, this is fishy, let's see what this CurrPage.ControlAddIn really is
      MyCodeunit.SetControlAddInAndInspectIt(CurrPage.ControlAddIn);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66011 Demo #2, #3 and #4 - Page
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=[ 2:50:26];
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      Marshaller@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Marshaller" WITHEVENTS;
      MyCodeunit@1001 : Codeunit 66011;

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      Marshaller := Marshaller.Marshaller();
      MyCodeunit.Initialize(Marshaller);
      MyCodeunit.DoStuff();
    END;

    EVENT Marshaller@1000::MarshalledEvent@8(args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      MESSAGE('I have just received message from JavaScript: %1',msg.Type);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66021 Demo #7 - Page (Html)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=17:04:14;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      HtmlRequest@1002 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      CurrPage.ControlAddIn.SendRequest(HtmlRequest.HtmlRequest('<div>Hello, World!</div><input type="button" value="Click me" onclick="alert(''I am clicked!'')">',TRUE).ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      MESSAGE('I have just received message from JavaScript: %1',msg.Type);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66022 Demo #7 - Page (Html + Css)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=12:13:08;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      HtmlRequest@1002 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";
      CssRequest@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.CssRequest";

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      SendRequest(HtmlRequest.HtmlRequest('<div class="hello">Hello, World!</div><input type="button" value="Click me" onclick="alert(''I am clicked!'')">',TRUE));
      SendRequest(CssRequest.CssRequest('.hello','font-size: 2em; color: steelblue; font-family: Segoe UI;'));
    END;

    LOCAL PROCEDURE SendRequest@2(Args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(Args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      MESSAGE('I have just received message from JavaScript: %1',msg.Type);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66023 Demo #7 - Page (Html callback)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=12:16:03;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      HtmlRequest@1002 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";
      CssRequest@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.CssRequest";

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      SendRequest(HtmlRequest.HtmlRequest('<div class="hello">Hello, World!</div><input id="btnClickMe" type="button" value="Click me" onclick="$$.Event.Message(''ButtonClick'',this.id)">',TRUE));
      SendRequest(CssRequest.CssRequest('.hello','font-size: 2em; color: steelblue; font-family: Segoe UI;'));
    END;

    LOCAL PROCEDURE SendRequest@2(Args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(Args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      CASE msg.Type OF
        'ButtonClick':
          BEGIN
            SendRequest(CssRequest.CssRequest('#' + FORMAT(msg.GetContent('Result')),'display: none;'));
            SendRequest(CssRequest.CssRequest('.hello','color: green'));
          END;
      END;
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66024 Demo #7 - Page (JavaScript)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=17:10:57;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      JavaScriptRequest@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.JavaScriptRequest";
      HtmlRequest@1001 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";
      TextIfTimeIsRunningOut@1002 : TextConst 'ENU="setInterval(function() { Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(""Message"",[{Type: ""Timer""}]); }, 1000)"';

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      SendRequest(JavaScriptRequest.JavaScriptRequest(TextIfTimeIsRunningOut));
    END;

    LOCAL PROCEDURE SendRequest@2(Args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(Args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      CASE msg.Type OF
        'Timer':
          BEGIN
            SendRequest(HtmlRequest.HtmlRequest('Ping.<br>'));
          END;
      END;
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66029 Demo #8 - Page (AngularJS)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=15:36:57;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      HtmlRequest@1002 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";
      JavaScriptRequest@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.JavaScriptRequest";
      CssRequest@1001 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.CssRequest";

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      SendRequest(HtmlRequest.HtmlRequest('<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>'));
      SendRequest(JavaScriptRequest.JavaScriptRequest('$$.FullScreen()'));
      SendRequest(CssRequest.CssRequest('*','font-family: Segoe UI;'));
      SendRequest(CssRequest.CssRequest('body, div, input','font-size: 12pt;'));
      SendRequest(CssRequest.CssRequest('#controlAddIn','padding: 24px 24px 24px 24px;'));
      SendRequest(HtmlRequest.HtmlRequest('<div ng-app=""><p>Name : <input type="text" ng-model="name"></p><h1>Hello {{name}}</h1></div>',FALSE));
    END;

    LOCAL PROCEDURE SendRequest@2(Args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(Args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      MESSAGE('I have just received message from JavaScript: %1',msg.Type);
    END;

    BEGIN
    END.
  }
}

OBJECT Page 66031 Demo #10 to #12 - Page (Sync)
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=17:24:32;
    Modified=Yes;
    Version List=TechDays2015;
  }
  PROPERTIES
  {
  }
  CONTROLS
  {
    { 1   ;    ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Field     ;
                Name=ControlAddIn;
                ControlAddIn=[My Control Add-In;PublicKeyToken=ea9604bef2a38877] }

  }
  CODE
  {
    VAR
      JavaScriptRequest@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.JavaScriptRequest";
      HtmlRequest@1001 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.Requests.HtmlRequest";
      TextIfTimeIsRunningOut@1002 : TextConst 'ENU="setInterval(function() { $$.Event.Raise(""Message"",[{Type: ""Timer""}]); }, 200);"';

    LOCAL PROCEDURE Initialize@1();
    BEGIN
      SendRequest(JavaScriptRequest.JavaScriptRequest(TextIfTimeIsRunningOut));
    END;

    LOCAL PROCEDURE SendRequest@2(Args@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.Events.MarshalledEventArgs");
    BEGIN
      CurrPage.ControlAddIn.SendRequest(Args.ToRequest());
    END;

    EVENT ControlAddIn@-2::ControlReady@2();
    BEGIN
      Initialize();
    END;

    EVENT ControlAddIn@-2::Message@3(msg@1000 : DotNet "'Vjeko.Com.ControlAddInTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ea9604bef2a38877'.Vjeko.Com.ControlAddInTemplate.JavaScript.Message");
    BEGIN
      CASE msg.Type OF
        'Timer':
          BEGIN
            SendRequest(HtmlRequest.HtmlRequest('Ping.'));
            SLEEP(1000);
          END;
      END;
    END;

    BEGIN
    END.
  }
}

OBJECT Page 76101 .NET Assemblies
{
  OBJECT-PROPERTIES
  {
    Date=19.11.15;
    Time=10:25:16;
    Modified=Yes;
    Version List=Vjeko.com.1.00;
  }
  PROPERTIES
  {
    SourceTable=Table76101;
    PageType=List;
    ActionList=ACTIONS
    {
      { 7       ;    ;ActionContainer;
                      ActionContainerType=ActionItems }
      { 8       ;1   ;Action    ;
                      Ellipsis=Yes;
                      CaptionML=ENU=Import Assembly...;
                      Promoted=Yes;
                      PromotedIsBig=Yes;
                      Image=ImportDatabase;
                      PromotedCategory=Process;
                      OnAction=BEGIN
                                 ImportAssembly();
                               END;
                                }
      { 6       ;1   ;Action    ;
                      Ellipsis=Yes;
                      CaptionML=ENU=Export Assembly...;
                      Promoted=Yes;
                      PromotedIsBig=Yes;
                      Image=ExportFile;
                      PromotedCategory=Process;
                      OnAction=BEGIN
                                 CALCFIELDS(Assembly);
                                 Assembly.EXPORT('C:\Temp\' + "Assembly Name" + '.dll');
                               END;
                                }
    }
  }
  CONTROLS
  {
    { 1   ;0   ;Container ;
                ContainerType=ContentArea }

    { 2   ;1   ;Group     ;
                Name=Group;
                GroupType=Repeater }

    { 3   ;2   ;Field     ;
                SourceExpr="Assembly Name" }

    { 4   ;2   ;Field     ;
                SourceExpr="User ID" }

    { 5   ;2   ;Field     ;
                SourceExpr=Tier }

  }
  CODE
  {

    PROCEDURE ImportAssembly@2();
    VAR
      TempBlob@1002 : Record 99008535;
      FileManagement@1001 : Codeunit 419;
      Asm@1003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Reflection.Assembly";
      InStr@1006 : InStream;
      FileName@1000 : Text;
      AllFilesTxt@1009 : TextConst 'ENU=All Files';
      ImportFileTxt@1008 : TextConst 'ENU=.NET Assembly';
      ImportTitleTxt@1005 : TextConst 'ENU=Import .NET Assembly';
    BEGIN
      FileName := FileManagement.BLOBImportWithFilter(
        TempBlob,ImportTitleTxt,'',
        ImportFileTxt + ' (*.dll)|*.dll|' + AllFilesTxt + ' (*.*)|*.*','*.*');

      IF FileName <> '' THEN BEGIN
        TempBlob.Blob.CREATEINSTREAM(InStr);
        InstallAssembly(InStr,Asm,'');
        CurrPage.UPDATE(FALSE);
      END;
    END;

    BEGIN
    END.
  }
}

