microsoft / AL

Home of the Dynamics 365 Business Central AL Language extension for Visual Studio Code. Used to track issues regarding the latest version of the AL compiler and developer tools available in the Visual Studio Code Marketplace or as part of the AL Developer Preview builds for Dynamics 365 Business Central.
MIT License
745 stars 244 forks source link

EvaluateCaptionClassAsync method generated with incorrect C# code. #7813

Closed rdebath closed 1 month ago

rdebath commented 3 months ago

Please include the following with each issue:

1. Describe the bug The C# code generated for a validated APP file gives a C# error CS0029 when published. It's been doing this for the last week or two.

2. To Reproduce Steps to reproduce the behavior:

The code below must be compiled into an App and PUBLISHED.

tableextension 50200 "TVTItem" extends Item
{
    fields
    {
        modify("Unit Price")
        {
            CaptionClass = TVT_GetCaptionClass(FieldNo("Unit Price"));
        }
        modify("Unit Volume")
        {
            CaptionClass = TVT_GetCaptionClass(FieldNo("Unit Volume"));
        }
        field(50200; "TVT Style Code"; Code[20])
        {
            DataClassification = CustomerContent;
            CaptionClass = TVT_GetCaptionClass50200;
        }
        field(50201; "TVT Target Cost"; Decimal)
        {
            CaptionClass = TVT_GetCaptionClass(FieldNo("TVT Target Cost"));
            Caption = 'Target Cost DF';
            DataClassification = CustomerContent;
        }
    }

    procedure TVT_GetCaptionClass(FldNo: Integer): Text[80]
    begin
        exit('This is a stand in for another FN call ' + Format(fldNo));
    end;

    procedure TVT_GetCaptionClass50200(): Text
    begin
        exit(TVT_GetCaptionClass(50200));
    end;

}

Note: Because the developers need to copy and paste the code snippet, including a code snippet as a media file (i.e. .gif) is not sufficient.

3. Expected behavior The compile of the generated C# should never throw an error due to incorrect code.

4. Actual behavior

2024-08-02T09:22:41.2606769Z ##[error]C# compilation has failed for the application object TableExtension_50200.
The failing c# file name is C20E4042DF9DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs. You can find this 
file with the associated AL file saved in the C:\ProgramData\Microsoft\Microsoft Dynamics 
NAV\250\Server\MicrosoftDynamicsNavServer$BC\apps\compilationerrors folder.
Detailed compilation error: C:\ProgramData\Microsoft\Microsoft Dynamics NAV\250\Server\MicrosoftDynamicsNavServer$BC\ap
ps\metadata\3\C2\C20E4042DF9DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs(60,29): error CS0029: Cannot 
implicitly convert type 'Microsoft.Dynamics.Nav.Runtime.NavText' to '(string, bool)'
C:\ProgramData\Microsoft\Microsoft Dynamics NAV\250\Server\MicrosoftDynamicsNavServer$BC\apps\metadata\3\C2\C20E4042DF9
DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs(62,29): error CS0029: Cannot implicitly convert type 
'Microsoft.Dynamics.Nav.Runtime.NavText' to '(string, bool)'
At C:\Program 
Files\WindowsPowerShell\Modules\BcContainerHelper\6.0.19\ContainerHandling\Invoke-ScriptInNavContainer.ps1:301 char:25
+                         throw $errorMessage
+                         ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (C# compilation ...tring, bool)'
:String) [], RuntimeException
    + FullyQualifiedErrorId : C# compilation has failed for the application object TableExtension_50200.
    The failing c# file name is C20E4042DF9DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs. You can find this 
    file with the associated AL file saved in the C:\ProgramData\Microsoft\Microsoft Dynamics NAV\250\Server\Microsof  
  tDynamicsNavServer$BC\apps\compilationerrors folder.
    Detailed compilation error: C:\ProgramData\Microsoft\Microsoft Dynamics NAV\250\Server\MicrosoftDynamicsNavServer$ 
   BC\apps\metadata\3\C2\C20E4042DF9DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs(60,29): error CS0029: Ca  
  nnot implicitly convert type 'Microsoft.Dynamics.Nav.Runtime.NavText' to '(string, bool)'
    C:\ProgramData\Microsoft\Microsoft Dynamics NAV\250\Server\MicrosoftDynamicsNavServer$BC\apps\metadata\3\C2\C20E40 
   42DF9DF7B042A078C9FC99B1C2D44FF52A97805C6342997E3549EB08FA.cs(62,29): error CS0029: Cannot implicitly convert type  
   'Microsoft.Dynamics.Nav.Runtime.NavText' to '(string, bool)'
2024-08-02T09:22:41.2667365Z ##[error]PowerShell exited with code '1'.
namespace Microsoft.Dynamics.Nav.BusinessApplication
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.Dynamics.Nav.Common.Language;
    using Microsoft.Dynamics.Nav.EventSubscription;
    using Microsoft.Dynamics.Nav.Runtime;
    using Microsoft.Dynamics.Nav.Runtime.Extensions;
    using Microsoft.Dynamics.Nav.Runtime.Report;
    using Microsoft.Dynamics.Nav.Types;
    using Microsoft.Dynamics.Nav.Types.Exceptions;
    using Microsoft.Dynamics.Nav.Types.Metadata;

    public sealed class TableExtension50200 : NavRecordExtension
    {
        public TableExtension50200(ITreeObject parent) : base(parent, 50200)
        {
        }

        public override string ObjectName => "TVTItem";
        public override bool __IsAsync => true;
        private new NavRecord ParentObject => (NavRecord)base.ParentObject;
        private NavRecord Rec => (NavRecord)base.ParentObject;
        private NavRecord xRec => (NavRecord)base.ParentObject.OldRecord;

        protected override ValueTask<object> OnInvokeAsync(int memberId, object[] args)
        {
            switch (memberId)
            {
                case 153013680:
                    if (args.Length != 1)
                        NavRuntimeHelpers.CompilationError(new NavNCLInvalidNumberOfArgumentsException("TVT_GetCaptionClass", 1, args.Length));
                    return TVT_GetCaptionClass((int)ALCompiler.ObjectToInt32(args[0])).AsValueTaskObject();
                    break;
                case 1678123946:
                    if (args.Length != 0)
                        NavRuntimeHelpers.CompilationError(new NavNCLInvalidNumberOfArgumentsException("TVT_GetCaptionClass50200", 0, args.Length));
                    return TVT_GetCaptionClass50200().AsValueTaskObject();
                    break;
                default:
                    NavRuntimeHelpers.CompilationError(Lang.WrongReference, memberId, 50200);
                    break;
            }

            return default;
        }

        public override async ValueTask<ValueTuple<string, bool>> EvaluateCaptionClassAsync(int fieldNo)
        {
            this.EnsureGlobalVariablesInitialized();
            switch (fieldNo)
            {
                case 50200:
                    return new((await this.TVT_GetCaptionClass50200()), true);
                case 50201:
                    return new((await this.TVT_GetCaptionClass(this.ParentObject.ALFieldNo(50201))), true);
                case 18:
                    return (await this.TVT_GetCaptionClass(this.ParentObject.ALFieldNo(18)));
                case 44:
                    return (await this.TVT_GetCaptionClass(this.ParentObject.ALFieldNo(44)));
            }

            return new(string.Empty, false);
        }

        public static TableExtension50200 __Construct(ITreeObject parent)
        {
            return new TableExtension50200(parent);
        }

        [NavFunctionVisibility(FunctionVisibility.External)]
        public ValueTask<NavText> TVT_GetCaptionClass50200()
        {
            TVT_GetCaptionClass50200_Scope_1678123946 \u03b2scope = new TVT_GetCaptionClass50200_Scope_1678123946(this);
            return \u03b2scope.InvokeAndDispose<NavText>((scope) => ((TVT_GetCaptionClass50200_Scope_1678123946)scope).\u03b3retVal);
        }

        [NavName("TVT_GetCaptionClass50200")]
        [SignatureSpan(8444309432827942L)]
        [SourceSpans(9007233616576553L, 9288704298385416L)]
        private sealed class TVT_GetCaptionClass50200_Scope_1678123946 : NavMethodScope<TableExtension50200>
        {
            public static uint \u03b1scopeId;
            [ReturnValue]
            public NavText \u03b3retVal = NavText.Default(0);
            protected override uint RawScopeId { get => TVT_GetCaptionClass50200_Scope_1678123946.\u03b1scopeId; set => TVT_GetCaptionClass50200_Scope_1678123946.\u03b1scopeId = value; }

            internal TVT_GetCaptionClass50200_Scope_1678123946(TableExtension50200 \u03b2parent) : base(\u03b2parent)
            {
            }

            protected override async ValueTask OnRunAsync()
            {
                StmtHit(0);
                this.\u03b3retVal = new NavText((await base.Parent.TVT_GetCaptionClass(50200)));
                return;
            }
        }

        [NavFunctionVisibility(FunctionVisibility.External)]
        public ValueTask<NavText> TVT_GetCaptionClass(int fldNo)
        {
            TVT_GetCaptionClass_Scope_153013680 \u03b2scope = new TVT_GetCaptionClass_Scope_153013680(this, fldNo);
            return \u03b2scope.InvokeAndDispose<NavText>((scope) => ((TVT_GetCaptionClass_Scope_153013680)scope).\u03b3retVal);
        }

        [NavName("TVT_GetCaptionClass")]
        [SignatureSpan(7036934548946977L)]
        [SourceSpans(7599858732695624L, 7881329414504456L)]
        private sealed class TVT_GetCaptionClass_Scope_153013680 : NavMethodScope<TableExtension50200>
        {
            public static uint \u03b1scopeId;
            [NavName("FldNo")]
            public int fldNo;
            [ReturnValue]
            public NavText \u03b3retVal = NavText.Default(80);
            protected override uint RawScopeId { get => TVT_GetCaptionClass_Scope_153013680.\u03b1scopeId; set => TVT_GetCaptionClass_Scope_153013680.\u03b1scopeId = value; }

            internal TVT_GetCaptionClass_Scope_153013680(TableExtension50200 \u03b2parent, int fldNo) : base(\u03b2parent)
            {
                this.fldNo = fldNo;
            }

            protected override async ValueTask OnRunAsync()
            {
                StmtHit(0);
                this.\u03b3retVal = new NavText(80, "This is a stand in for another FN call " + NavFormatEvaluateHelper.Format(this.Session, ALCompiler.ToNavValue(this.fldNo)));
                return;
            }
        }
    }
}

A clear and concise description of what happened accompanied by images, animations, or a link to a video showing the issue occurring

5. Versions:

Final Checklist

Please remember to do the following:

steveendow commented 2 months ago

Hi, are there any plans to review this? Two of our NextMajor pipelines have been failing since July 19 due to this error when there is an assignment to CaptionClass.

##[error]Install-NAVApp: 
Line |
  15 |      $output = Install-NAVApp @cmdletArgs;
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~
     | C# compilation has failed for the application object PageExtension_70911617.
The failing c# file name is EDF5DE6AF6D9B2F2AA6668AD9870C067A982468C7B0703D4A48D76A2CAA69095.cs. You can find this file with the associated AL file saved in the c:\DatabasesVol\ALAssemblies\apps\compilationerrors folder.
Detailed compilation error: c:\DatabasesVol\ALAssemblies\apps\metadata\3\ED\EDF5DE6AF6D9B2F2AA6668AD9870C067A982468C7B0703D4A48D76A2CAA69095.cs(41,28): error CS0029: Cannot implicitly convert type 'Microsoft.Dynamics.Nav.Runtime.NavText' to '(string, bool)'
rdebath commented 2 months ago

Um @steveendow they seem to have got rid of my error for NextMajor (V25) between the 17th and the 24th of August (Maybe as part of the V26 split) and my tests are running again.

Do you need to refresh a Docker Image ? Though I notice that your issue is on a PageExt, mine was on a TableExt. Perhaps it's not exactly the same issue and they'll need an example.

Hmm, tests; some of my APPs don't have tests, if they might have only half fixed this I need to check those.

steveendow commented 2 months ago

Thanks for the update. Unfortunately, we still received the error as of August 29.

Build pipeline: NextMajor Finished: Thu, Aug 29 2024 22:39:10 GMT+00:00

We use COSMO Alpaca for our pipelines, so I don't believe that the Docker Image should be an issue. I was not able to find the Container version info in the pipeline log--I'll have to contact COSMO to see how to find that info.

Thank you for the observation that your error was related to a Table Extension, and our error is related to a Page Extension.

pageextension 70911617 "AP VEND Log EXT BLD" extends "Vendor Card"
{
    layout
    {
        modify("Name 2")
        {
            CaptionClass = VendorName2Caption;
            Visible = true;
        }
    }
steveendow commented 2 months ago

We just re-ran our NextMajor pipeline and it is still failing on the Publish App step.

COSMO showed me how to find the BC Container version. The version today is: sandbox-25.0.23364.23502-us

thloke commented 1 month ago

This is a bug that we've fixed fairly recently, the bugfix should be in version 25.0.23862.0 of the platform or greater.

rdebath commented 1 month ago

Confirmed for 26.0.23876.0 too.

KuljitSinghParmar commented 1 month ago

@thloke when it will available? i just created new BC25 sandbox and its - Version: US Business Central 25.0 (Platform 25.0.23623.0 + Application 25.0.23364.23635)

thloke commented 1 month ago

@thloke when it will available? i just created new BC25 sandbox and its - Version: US Business Central 25.0 (Platform 25.0.23623.0 + Application 25.0.23364.23635)

I'm not sure when the SaaS sandboxes will be updated, but the docker images should have the fixed build already.