JsonDataSource Conditional Expressions: !s.Disabled Fails, Requires s.Disabled==false When Using json instead of POCOs

When we were passing a POCO this would work:

<<if [MyProperty.Data.Any(s => !s.Disabled)]>>

When we changed to pass an interface (Data changed to a List instead of List), properties in sub interfaces could not be found so we decided to try and pass it as Json with JsonDataSource but then we get the error:

System.InvalidOperationException: Tag 'if' is not well-formed. A conditional expression should return a Boolean value.

and need to change to

<<if [MyProperty.Data.Any(s => s.Disabled==false)]>>

What’s the best way to approach this? And why is not !s.Disabled work when using other than POCO?

Please let me know if you’ll need any additional information.
GroupDocs.Assembly version 24.12.0

@oskarj

What is happening

  • When the data source is a POCO the expression is compiled against the actual .NET type (bool Disabled). The C# unary operator ! is therefore understood and the template works.
  • JsonDataSource does not deserialize the JSON into a POCO; it creates a dynamic object (JObject/JToken). The expression engine used by Assembly evaluates the condition on those dynamic values. The unary ! operator is not supported for a JToken/dynamic value, so the parser throws
System.InvalidOperationException: Tag 'if' is not well‑formed. A conditional expression should return a Boolean value.

Hence you must use an explicit Boolean comparison (s.Disabled == false or s.Disabled != true).

How to make it work reliably

  1. Ensure the JSON field is a proper JSON boolean ("Disabled": true / "Disabled": false).

  2. Use the equality form in the template, e.g.:

    <<if [MyProperty.Data.Any(s => s.Disabled == false)]>>
    

    or, if you prefer a negation style:

    <<if [MyProperty.Data.Any(s => s.Disabled != true)]>>
    
  3. If you need the ! syntax, convert the JSON to a POCO before passing it to the template, e.g.:

    var list = JsonConvert.DeserializeObject<List<MyImplementation>>(json);
    editor.DataSource = new JsonDataSource(list);
    

    (or use ObjectDataSource with the POCO list).

  4. Upgrade – the latest GroupDocs.Assembly release contains a small fix that improves handling of boolean values in JsonDataSource. If you can, move to the newest version and retest.

What we need to verify

  • A minimal JSON sample that reproduces the error (show the Disabled field).
  • The interface definition (IMyInterface) you are using with JsonDataSource.
  • The exact stack trace (if any) beyond the “Tag ‘if’ is not well‑formed” message.

Providing those details will let us confirm whether the issue is purely the expression‑parser limitation or if there is an underlying bug that needs to be logged.

Hi @oskarj !

Thank you for using GroupDocs.Assembly!

I would be glad to help you. if notes and suggestions from our AI consulting do not help you - please provide source code and all corresponding files

  • json data source
  • template document

This will help us to investigate the issue and provide solution and fix potential bug in the code.

There were few changes related to the inline template processing in the latest release - I would also recommend to verify changes on latest version.

Thank you!

Hi Yuriy, thank you for your reply!
I have reverted back to not use json anymore, but go for the POCO approach, I don’t think that it’s a bug but rather a bad implementation, that it should not be dependent on what source I’m using if I could use !s.Disabled vs s.Disabled == false.

Can you please explain why hiearchy is not working when I’m using interfaces, for example:

public interface IBlockDisabled
{
bool Disabled { get; set; }
}

public interface IBlock : IBlockDisabled
{
string Name { get; set; }
}

If i pass in a List I can use the property “Name” but not “Disabled” but if I do

public interface IBlock : IBlockDisabled
{
string Name {get;set;}
new bool Disabled { get; set; }
}
I can use both. I would be nice to be able to use the whole interface.

At some point I tested with the latest version, but I couldn’t see any improvements.

//Oskar

@oskarj

Hm, that need to check on your particular data and document template

Can you please share simple solid solution/project that will demonstrate your scenario?
It’s really important to obtain all information

  • solution/project
  • data source
  • template

Here is an example project

I tried some with JsonDataSource but can’t get any data out.

GroupDocs.Example.zip (24.1 KB)

@yuriy.mazurchuk did you get a change to take a look at this?

@oskarj
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): ASSEMBLYNET-92

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

No thanks, some things I just assume will work when I pay for an expensive license.
Please let me know when a fix is available and where I can track the issue

@oskarj

Hello, sorry for the delay in reply

Two suggestions to fix your code:

1. Add the Disabled and Title properties in ISampleBlockItem (if this fits your design)

public interface ISampleBlockItem : IBlockItem
{
    string SampleProperty { get; set; } 
    bool Disabled { get; set; }
    string Title { get; set; }
}

2. Fix JSON serialization
Currently the serialized JSON is not complete and doesn’t include the Data list.
To build a complete JSON there are few approaches including attributes, but the simplest one is to change the serialization to use object type, which will serialize the actual runtime types

var jsonString = JsonSerializer.Serialize(blocks.Cast<object>().ToList());
var jsonDataSource = new JsonDataSource(new MemoryStream(Encoding.UTF8.GetBytes(jsonString)));

In case you apply both changes the code will work for both - object model and JSON.

Feel free to share if it helps, or ask questions if you have any.

Thanks

Hi!
Thanks!
I can’t make those changes suggested in 1) it will break other things and stink up the code base
regarding 2 so is not my intention to use Json, just added it as a way to show that it’s not working.
//OJ

@oskarj

Thanks for checking, we are currently exploring a possible solution according to your requirements.

1 Like