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
719 stars 242 forks source link

al/createPackage fails due to invalid custom xml part #7704

Closed adcprowi closed 2 months ago

adcprowi commented 3 months ago

1. Describe the bug The package can not be created after adding a new row in a repeating section for a word layout. The following error is displayed:

Processing of message 'al/createPackage' failed with error: 'One or more errors occurred. (Failure while emitting metadata for object:'ReportExtension PRD_SalesOrderConfirmation' (Invalid Custom Xml part format))' Details: System.AggregateException: One or more errors occurred. (Failure while emitting metadata for object:'ReportExtension PRD_SalesOrderConfirmation' (Invalid Custom Xml part format)) ---> System.AggregateException: Failure while emitting metadata for object:'ReportExtension PRD_SalesOrderConfirmation' (Invalid Custom Xml part format) ---> System.InvalidOperationException: Invalid Custom Xml part format at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportChangeMetadataComparer.CalculateElementInfo(XElement element, String parentPath) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\ReportChangeMetadataComparer.cs:line 85 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportChangeMetadataComparer.MapElementsToDictionary(Dictionary2 oldElements, XElement oldXml, String parentPath) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\ReportChangeMetadataComparer.cs:line 135 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportChangeMetadataComparer.MapElementsToDictionary(Dictionary2 oldElements, XElement oldXml, String parentPath) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\ReportChangeMetadataComparer.cs:line 152 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportChangeMetadataComparer.MapElementsToDictionary(Dictionary2 oldElements, XElement oldXml, String parentPath) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\ReportChangeMetadataComparer.cs:line 152 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportChangeMetadataComparer.CompareReportMetadata(XElement oldXml, XElement newXml, String customXmlRootName) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\ReportChangeMetadataComparer.cs:line 45 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.WordDocumentUpdate.ApplyFieldWordRenames(XDocument oldCustomXmlPart, Stream wordLayoutSource) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\Word\WordDocumentUpdate.cs:line 587 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportWordUtilities.UpdateWordFileIfNeeded(IFileSystem fileSystem, String docName, String officeCustomXmlPart, String officeCustomXmlPart_Extended) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportEmitterUtilities\ReportWordUtilities.cs:line 69 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportLayoutsGenerator.GenerateLayout(ReportTypeSymbol symbol, ApplicationObjectTypeSymbol declaringSymbol, DiagnosticBag diagnostics, ReportLayoutSymbol layoutSymbol, Action4 generator) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportLayoutsGenerator.cs:line 46 at Microsoft.Dynamics.Nav.CodeAnalysis.Emit.ReportExtensionLayoutsEmitter.Emit(DiagnosticBag diagnostics) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Emitter\ReportExtensionLayoutsEmitter.cs:line 23 at Microsoft.Dynamics.Nav.CodeAnalysis.MethodCompiler.EmitNonObjectCode(Symbol objectType, Action1 emitter) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compiler\MethodCompiler.cs:line 205 --- End of inner exception stack trace --- at Microsoft.Dynamics.Nav.CodeAnalysis.MethodCompiler.EmitNonObjectCode(Symbol objectType, Action1 emitter) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compiler\MethodCompiler.cs:line 209 at Microsoft.Dynamics.Nav.CodeAnalysis.MethodCompiler.CompileObject(ObjectTypeSymbol containingType) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compiler\MethodCompiler.cs:line 189 at Microsoft.Dynamics.Nav.CodeAnalysis.Symbols.SymbolVisitor.VisitApplicationObjectExtensionType(ApplicationObjectExtensionTypeSymbol node) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Generated\SymbolVisitor.Generated.cs:line 356 at Microsoft.Dynamics.Nav.CodeAnalysis.MethodCompiler.<>c__DisplayClass11_0.b__0(Symbol memberSymbol) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compiler\MethodCompiler.cs:line 129 --- End of inner exception stack trace --- at Microsoft.Dynamics.Nav.CodeAnalysis.MethodCompiler.CompileModule(ModuleSymbol moduleSymbol) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compiler\MethodCompiler.cs:line 140 at Microsoft.Dynamics.Nav.CodeAnalysis.Compilation.CompileImpl(ModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate1 filterOpt, Predicate1 radCompilationFilter, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\Compilation.cs:line 1216 at Microsoft.Dynamics.Nav.CodeAnalysis.Compilation.Compile(ModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate1 filterOpt, Predicate1 radCompilationFilter, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\Compilation.cs:line 1188 at Microsoft.Dynamics.Nav.CodeAnalysis.CommandLine.CommonCompiler.PackageTheModule(Compilation compilation, CompilerTextWriter consoleOutput, CancellationToken cancellationToken, ErrorLogger errorLogger, AnalyzerDriver analyzerDriver, Predicate1 filterOpt, Predicate1 radCompilationFilter) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\CommandLine\CommonCompiler.cs:line 808 at Microsoft.Dynamics.Nav.CodeAnalysis.CommandLine.CommonCompiler.RunCoreImpl(CompilerTextWriter consoleOutput, ErrorLogger errorLogger, Compilation compilation, AnalyzerDriver analyzerDriver, IEnumerable1 analyzerExceptionDiagnostics, IEnumerable1 additionalTextFiles, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\CommandLine\CommonCompiler.cs:line 561 at Microsoft.Dynamics.Nav.CodeAnalysis.CommandLine.CommonCompiler.RunCore(CompilerTextWriter consoleOutput, ErrorLogger errorLogger, ITelemetryService telemetryService, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\CommandLine\CommonCompiler.cs:line 491 at Microsoft.Dynamics.Nav.CodeAnalysis.CommandLine.CommonCompiler.Run(CompilerTextWriter consoleOutput, ITelemetryService telemetryService, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\CommandLine\CommonCompiler.cs:line 341 at Microsoft.Dynamics.Nav.EditorServices.Protocol.Utility.ActiveProjectBuilder.Build(VsCodeWorkspace workspace, Project builtProject, StreamingTextWriter outputWriter, Boolean isRad, IList1 args, CancellationToken cancellationToken, IResponseQueue responseQueue, ITelemetryService telemetryService, Boolean forceBuild, IList1 outputFiles, CustomTelemetryEvent telemetryEvent, String requestVsCodeExtensionVersion) in X:\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\Utility\ActiveProjectBuilder.cs:line 204 at Microsoft.Dynamics.Nav.EditorServices.Protocol.Utility.ActiveProjectBuilder.BuildWorkspaceAsync(CancellationToken cancellationToken, IFileSystem fileSystem, VsCodeWorkspace workspace, String projectDir, IList1 args, Boolean buildDependencyPackage, Boolean isRad, IResponseQueue responseQueue, Boolean forceBuildOfAllDependencies, CustomTelemetryEvent telemetryEvent, ITelemetryService telemetryService, String vsCodeExtensionVersion) in X:\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\Utility\ActiveProjectBuilder.cs:line 115 at Microsoft.Dynamics.Nav.EditorServices.Protocol.LanguageServer.Extensions.CreatePackageRequestHandler.HandleAsync(CreatePackageRequest request, Int32 requestId, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\LanguageServer\Extensions\CreatePackageRequestHandler.cs:line 37 at Microsoft.Dynamics.Nav.EditorServices.Protocol.MessageProtocol.RequestHandlerBase1.HandleAsync(JToken requestContents, Int32 requestId, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\MessageProtocol\RequestHandlerBase.cs:line 84 at Microsoft.Dynamics.Nav.EditorServices.Protocol.RequestRegistry.Process(Message message) in X:\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\Endpoints\RequestRegistry.cs:line 84

2. To Reproduce

  1. Create a report extension. I'm extending the Standard Sales Order Confirmation.
  2. Define a word layout for the report extension.
  3. Create a table with one row in the word layout and add a repeater to it for something like the sales line data.
  4. Add a new row within the repeater control. image
  5. Close the Word document and build the AL project.
reportextension 50000 PRD_SalesOrderConfirmation extends "Standard Sales - Order Conf."
{
    WordLayout = './Layout/StandardSalesOrderConfirmation.docx';
    dataset
    {
        addlast(Line)
        {
            dataitem(PRD_ReservationEntry; "Reservation Entry")
            {
                DataItemLink = "Source ID" = field("Document No."), "Source Ref. No." = field("Line No.");
                DataItemTableView = where("Source Type" = const(37), "Source Subtype" = const(1));
                DataItemLinkReference = Line;
                column(Entry_No; "Entry No.")
                {

                }
                column(Item_No; "Item No.") { }
                column(Serial_No; "Serial No.")
                {

                }
            }
        }
    }
}

StandardSalesOrderConfirmation.docx

3. Expected behavior The package should be created. My goal was to add a nested repeater inside of the second row which contains data from the reservation entries linked to the sales line.

4. Actual behavior The package is not created after adding a new row to the repeater control and an error message is displayed.

5. Versions:

BazookaMusic commented 3 months ago

Could you also attach a a sample word layout that shows the error? It would help speed up the fix to this issue

adcprowi commented 3 months ago

StandardSalesOrderConfirmation.docx

thloke commented 2 months ago

I can reproduce this with the layout that you supplied. The reason for the crash is that the layout has a weird custom XML part where we expect the business central specific properties to reside. I can fix the crash so that it gives a nicer error message, but it doesn't address the fact that this layout is malformed. I tried re-creating a similar layout with the steps that you provided, but I couldn't get the same malformed layout.

I assume there was nothing special about the steps you took to create the repeater? I.e. - the steps you took follow the ones outlined here: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-howto-report-layout#using-tables-to-display-data-from-the-report-dataset-simple-repeaters

If so, can you try to re-create the word layout again and see if you can consistently reproduce the crash?

thloke commented 2 months ago

Ignore all of that, I completely overlooked the most important step:

Add a new row within the repeater control.

You even highlighted it for me, sorry. :( I can repro the same behaviour now.

thloke commented 2 months ago

The reason why this breaks is that when you add a new line to a repeater in Word, it inserts a duplicate element which causes the exception in our compiler. I've fixed the issue where the compiler throws an exception, but it will not address the fact that there is a duplicate element which even if we allow for compilation (we do not), the server will reject.

So in short, the fix for this will be simply to have no unhandled exception but it won't change the fact that the layout will be invalid. Allowing duplicate elements is a bigger problem and the fix will have to involve the server as well. We could delete the duplicate element but that would be a destructive change on the layout which has its own perils with destroying user data.

I'm surprised we haven't run into this before.

adcprowi commented 2 months ago

Thanks for looking into this. I do believe there's more to this issue. This error message has been referenced in the past for similar use cases: https://github.com/Microsoft/AL/issues/3880#issuecomment-611371338

The reason for the duplicate element is because I've been trying to create a nested repeater in different ways. This time I created a table with 2 rows first and put the sales line repeater around these 2 rows. I created the nested repeater inside of the second row and added some data. image

When I run this report the output is completely blank. (I can see sales line and reservation entry data in the xml output) image

It should be possible to create a nested repeater in the word layouts according to the documentation. The steps to create a nested repeater are not specified here but I've looked at feedback from similar issues and nothing seems to work. https://github.com/microsoft/AL/issues/6628 https://github.com/Microsoft/AL/issues/3880

There's more strange behaviour that makes me think something is not right. I recreated the word file from scratch and added a new table. When I add the repeating content control the xml mapping is not shown. image I need to close the word file and rebuild my AL application to apply the mapping. image

Can you please check if you are able to create and display a nested repeater? Here's my word layout based on the same code: StandardSalesOrderConfirmation.docx

thloke commented 2 months ago

@KennieNP - Do we have docs on creating nested repeaters in Word layouts? I'm not too familiar with this.

JesperSchulz commented 2 months ago

The fix for this issue has been checked in to the master branch. It will be available in the bcinsider.azurecr.io/bcsandbox-master Docker image starting from platform build number 25.0.18404.0 and VS Code Extension Version 14.0.986719.

If you don’t have access to these images you need to become part of the Ready2Go program: aka.ms/readytogo

For more details on code branches and docker images please read: https://blogs.msdn.microsoft.com/nav/2018/05/03/al-developer-previews-multiple-releases-and-github/ https://freddysblog.com/2020/06/25/working-with-artifacts/