Can not iterate over an instance of type 'System.Object

Good day,

we need some help with two issues which are best illustrated with a simple example.

Take a default setup, with:
Options = DocumentAssemblyOptions.AllowMissingMembers

JsonDataSource:
{}

Template:
<<var [bar = barbar]>>
<<foreach [foo in barbar]>><</foreach>> // no problem, we have "AllowMissingMembers"
<<if [false]>> // code inbetween if-statement gets "evaluated"
<<foreach [foo in bar]>><</foreach>> // results in an error (because of var-assignment)
<</if>>

The error is something like “Can not iterate over an instance of type ‘System.Object’”.

The combination of these two issues is a problem for us.
We need to use “var” because our statements can become very complex and need to be split up.
But we have no way to check if “var” is usable, like check for a null value, without triggering the error.

Would you be so kind to assist?

Thanks and regards,

TerrraIndex

1 Like

This is a very annoying bug, because in json field/array’s are optional/nullable and not the whole report crashes when an array is not provided.

If you make it possible that when a var is created, you can set the type to Enumerable of Array instead of Object. It’s all fixed.

<<var [array bar = barbar]>>
or
<<var [IEnumerable bar = barbar]>>

1 Like

@nosweat @TerraIndexService

We are investigating this scenario. Your investigation ticket ID is ASSEMBLYNET-233. You’ll be notified in case of any update.

1 Like

@TerraIndexService @nosweat

<<if [false]>> // code inbetween if-statement gets "evaluated"`
   <<foreach [foo in bar]>><</foreach>> // results in an error (because of var-assignment)`
<</if>> 

Actually, tags within a false-if branch are never evaluated, but are always parsed. And the error encountered is a parse-time error.

GroupDocs.Assembly supports a subset of C# language in its template syntax and mimics C# compiler behavior to some extent. For example, parsing of template syntax corresponds to compile time. Thus, parsing of a whole template happens all the time before evaluation of its very first expression.

Actually, this is not a bug. Here is a relevant quote from the DocumentAssemblyOptions.AllowMissingMembers reference:
Specifies that missing object members should be treated as null literals by the assembler.

So, when DocumentAssemblyOptions.DocumentAssemblyOptions is applied, <<var [v = missingMember]>> becomes <<var [v = null]>>. In pure C#, on attempt to use a construction like var v = null, a compile-time error appears, because the type of the variable cannot be determined. GroupDocs.Assembly is less restrictive and allows to proceed, but it cannot determine the type of a variable from a null literal as well, so it fallbacks to object.

We cannot simply use, for example, IEnumerable in this case. That said, there is a technical possibility for passing information about missing members further to variables initialized from them and we plan to proceed in this way, but it requires time.

Thanks for your response!

That said, there is a technical possibility for passing information about missing members further to variables initialized from them and we plan to proceed in this way, but it requires time.

Do you mean that you are working on this improvement? Any timeframe available?

A way to make this work would be a life-saver for us:
using Options = DocumentAssemblyOptions.AllowMissingMembers;

<<var [bar = data.propertyThatMayOrMayNotExist.Collection]>> // real statements used are far more complex and need to be split up
<<foreach [foo in bar]>><</foreach>> // results in "Can not iterate over an instance of type System.Object"

@nosweat

We cannot share any ETA at the moment (we’ll notify you as soon as we have the ETA).

Hi, then this is still a Bug, because in that case it should not complain about iterating a System.object. Then is should be able to use the null check, and not throwing a parse error. But there is no single null check avaible once you go into a foreach or when you try to get an extra filter or function on a null variable.

  • The foreach should check the null
  • and the bar?.Where() should not throw an parse error

@TerraIndexService

We’ll continue our investigation and will notify you in case of any progress update.

@TerraIndexService

Here are further details from a technical perspective.

As a workaround, to avoid repeating of complex expressions in templates, you may consider transformation of your data being passed to DocumentAssembler.

As explained earlier, when DocumentAssemblyOptions.DocumentAssemblyOptions is applied, <<var [v = missingMember]>> becomes <<var [v = null]>>. If a statement like var v = null; foreach (var i in v) { } in pure C# is compiled, then a compile-time error regarding its first step (that is, var v = null;) appears. So overall, the scenario does not work.
When corresponding template syntax is used, GroupDocs.Assembly does not raise an error on the first step, but raises an error on the second one. So overall, the scenario does not work either, the same way as for pure C#.
The main technical reason for this is that C# does not have a type for a null literal, so both a C# compiler and GroupDocs.Assembly do not support the scenario, but report about the error at different times, which may be confusing.

However, we do understand inconveniences that you face, so we plan to work on support of the scenario (which is technically possible). But we cannot share any ETA.

1 Like

Thank you for your understanding.

We are looking forward to hearing from you.

@nosweat

You’re welcome.

Any news, or any known workaround available at the moment?

Thanks.

@nosweat

No updates or changes have occurred regarding the ticket at this time. We apologize for any inconvenience caused. For more information, including any available workarounds, please refer to our previous comment. Thank you for your understanding.

Hi Atir,
do you now have any update?
Because the workaround is not workable for us, and we are having some projects being blocked by this issue.

@TerraIndexService

If the suggested workaround is not suitable, you can try resolving the issue by simply copying and pasting the template expressions. We apologize for any inconvenience caused.

Is there any way to get this issue solved, it is one of our 2 issues what is blocking us from deploying the new reporting to production. We have many customers waiting for this feature, and our complete investment is hanging on this issue. So is there any way, maybe financial, maybe source code?

@TerraIndexService

We kindly request your patience as we conduct further investigations.

From a technical perspective:

Not being able to null-check a var means any conditional expression will break when data is missing.
Think of conditional formatting, filtering, and also inner-foreach.

Transforming the input is not an option, because that would mean to completely flatten the data structure. This would no longer allow us to create many rich reports from a single dataset, which is the greatest strength of GroupDocs in our opinion.

This statement would fail in C#, as var requires an underlaying type;
var test = null
Perhaps in GroupDocs the type can become object or pref. dynamic, which can be null-checked;
var test = (dynamic)null
I guess we should then be able to do something like this;
var test = data?.collection ?? new List<dynamic>()
foreach (foo in test) { }

@nosweat @TerraIndexService

To expedite the resolution of your issue, you have the option to opt for priority/paid support. This will ensure dedicated attention and faster assistance.

please, what would the price be to fix this issue?