Reporting, Json Loading, Engine tries to evaluate expression inside of false if statement

When using a json data source there is a situation where data may not be present inside of the json due to conditional expressions. Since the entire model is not sent each time, some objects/arrays might be null. However the Reporting engine does not respect if blocks and tries to parse the entire template. This causes an error since some data is not present.

In the example attached is a json structure that has a list of tasks that is currently null. But due to enclosing if brackets should not be evaluated. The engine however tries to evaluate the internal for loop which obviously does not exist causing it to throw an exception.

BrokenJsonLoading.zip (11.5 KB)

@nross

Please use ReportingEngine.Options as shown below to avoid this exception. Hope this helps you.

engine.Options = ReportBuildOptions.AllowMissingMembers;
engine.BuildReport(
        baseDoc,
        new JsonDataSource(MyDir + "BuggyLoadJson.Json", jop),
        "Sec"
        );

@tahir.manzoor
This does exactly help, as we use expect our unit tests to fail on missing members. If missing members are allowed then there is no guarantee what has happened inside the template.

Furthermore, this does have a performance impact as the engine is currently wasting resources processing code that is does not need to.

@nross

Could you please share some more detail about your requirement along with test case why you do not want to use AllowMissingMembers? We will then log the issue accordingly in our issue tracking system.

@nross

There are many same queries in the forum by you about LINQ Reporting. So, we would like to clarify the following point about LINQ Reporting Engine.

LINQ Reporting Engine works with expressions in two stages:

  1. Parsing all expressions through a template. This stage is similar to compiling a program. At this stage, expressions are just parsed and none of them are evaluated, so none of expressions are skipped from further parsing.

  2. Evaluation of expressions. This stage is similar to running a previously compiled program. At this stage, expressions are evaluated according to logic defined through tags in a template. These can be not all expressions. For example, if an expression defined for an if tag returns false, then none of nested expressions corresponding to the if branch are evaluated (otherwise, it would not have any sense). This statement can be easily verified using the following code.

         Console.WriteLine("Test no throwing.");
         TestIfTagEvaluation("false"); // This does not throw, because <<[ThrowingMember]>> is not evaluated in this case.
    
         Console.WriteLine("Test throwing.");
         TestIfTagEvaluation("true"); // This throws, because <<[ThrowingMember]>> is evaluated in this case.
    
         Console.WriteLine("Never get here."); 
    
     //----------------------------------------------------------
    
     private static void TestIfTagEvaluation(string expression)
     {
         DocumentBuilder builder = new DocumentBuilder();
         builder.Write("<<if [" + expression + "]>><<[ThrowingMember]>><</if>>");
    
         ReportingEngine engine = new ReportingEngine();
         engine.BuildReport(builder.Document, new TestDataSource());
     }
    
     public class TestDataSource
     {
         public object ThrowingMember
         {
             get { throw new Exception("Testing if tag evaluation."); }
         }
     }
    

To recap, lack of a member is checked during parsing of a template and has nothing to do with evaluation of an expression. In fact, an expression referencing a missing member is never evaluated: It either causes an exception or is replaced with a null literal depending on whether ReportBuildOptions.AllowMissingMembers is applied.

As far as performance is concerned, processing template expressions in the two stages makes it only faster to work with data bands iterating through a huge amount of items and does not add any significant overhead in other scenarios.

1 Like

@tahir.manzoor Thank you for all of your support, I have appreciated all of your answers.
Thank you for clarifying this as I was under the impression that the engine was working like JS were it was parsing and evaluating at the same time.

@nross

Thanks for your feedback. Please feel free to ask if you have any question about Aspose.Words, we will be happy to help you.