I'm not using IRISObjects, just ClassMethodString:

PersonData = JsonSerializer.Deserialize<PersonDataClass>(App.Iris.ClassMethodString("API.Calls.Operative", "Checking", CardNo.Text));
            if (PersonData != null)
            {
                if (!PersonData.IsValid)
                {
                    SystemSounds.Exclamation.Play();
            }

Hi.

Tnx for your quick reply.

Here is the class method:

ClassMethod Checking(CardNo As %String) As %String [ Language = objectscript ]
{
Set person=##class(MasterData.Person).CardNoOpen(CardNo,4)
Quit:person="" "null"

Set checking=##class(Production.Checking).%New()
Set checking.Person=person
Set checking.Condition.Type=person.Condition.Type
Set checking.Condition.ValidBy=person.Condition.ValidBy
Set checking.ConditionIsValid=(person.Condition.ValidBy>=+$Horolog)
Do checking.%Save()

Set model=##class(API.Models.Operative.PersonGetData).%New()
Set model.Ident=person.Ident
Set model.FirstName=person.FirstName
Set model.LastName=person.LastName
Set model.Department=person.Department.Name
Set model.IsValid=checking.ConditionIsValid

If ('checking.ConditionIsValid)
{
Set person.Condition.Type="T"
Set person.Condition.ValidBy=+$Horolog+6
Do person.%Save()
}

Do model.%JSONExportToString(.json)

Do ##class(MasterData.Person).%UnlockId(person.%Id())

Quit json
}

I'm using now %UnlockId method instead of setting the object to null.

Regards,
Matjaž

Bellow is modified Load method:

ClassMethod Load(Ident As %String) As %String [ Language = objectscript ]
{
Set data=##class(User.Data).%OpenId(Ident)
Quit:data="" "null" // Original
Set model=##class(User.Model).%New()
Set model.Ident=data.Ident
Do model.PNG.CopyFrom(data.PNG)
Do model.%JSONExportToString(.json) Set file=##class(%File).%New("C:\Tmp\1.txt") //Log the json string
Do file.Open("WSN")
Do file.Write(json)
Do file.Close() // Workaround
Set model=##class(User.Model).%New()
Set model.Ident=data.Ident
Do model.%JSONExportToString(.json) // CHANGE in workaround
Set a={}.%FromJSON(json)
Do a.%Set("PNG",data.PNG,"stream>base64")
// Set file=##class(%File).%New("C:\Tmp\2.txt") //Log the json string
Do file.Open("WSN")
Do file.Write(a.%ToJSON())
Do file.Close() Quit json
}

Compare files 1.txt and 2.txt, they are different, but they should be equal. With string recorded in 2.txt c# app doesn't throw the exception.

Hi.

I've tried already with method %JSONExportToStream but C# InterSystems.Data.IRISClient.ADO.IRIS native provider does not have method to return stream. And I checked the string length on server side and client (C#) side - they are the same. As I've already mentioned the workaround in method Load works fine, so the string length is not the problem.

Pls check your e-mail for attached PNG.

Regards, Matjaž.

Hi.

I use the model class when I want to export some extra data (e.g properties from referenced objects) - model class attached is just a demo class to reproduce behaviour. I've also tried to export on origin class as you've suggested but the result is the same. If I open saved stream on server it looks as a valid PNG file. Maybe you should test with larger PNG file to reproduce the error, because it works also fine for me with smaller PNGs.

About IdKey index it is my habit to add the Unique parameter, although it is unique by it self :)...

I use a workaround in Load method which creates a valid Base64 string on output:

Set data=##class(User.Data).%OpenId(Ident)
Quit:data="" "null"

Set model=##class(User.Model).%New()
Set model.Ident=data.Ident

Do model.%JSONExportToString(.json)

Set jsonBase64={}.%FromJSON(json)
Do jsonBase64.%Set("PNG",data.PNG,"stream>base64")

Quit jsonBase64.%ToJSON()

I did also some logging on strings created with original Load method and workaround and it shows many differences... And I did it on IRIS server to ensure no extra encoding/decoding is done.

Viele Grüsse nach Wien.

Matjaž

Hi.

Tnx for reply. 

Classes:

Class User.API [ Abstract ]
{

ClassMethod Load(Ident As %String) As %String [ Language = objectscript ]
{
Set data=##class(User.Data).%OpenId(Ident)
Quit:data="" "null"

Set model=##class(User.Model).%New()
Set model.Ident=data.Ident
Do model.PNG.CopyFrom(data.PNG)

Do model.%JSONExportToString(.json)

Quit json
}

ClassMethod Save(Ident As %String, Data As %String) As %Status [ Language = objectscript ]
{
Set data=##class(User.Data).%OpenId(Ident)
If (data="")
{
Set data=##class(User.Data).%New()
Set data.Ident=Ident
}

Set model=##class(User.Model).%New()
Do model.%JSONImport(Data)

Do data.PNG.CopyFrom(model.PNG)

Quit data.%Save()
}

Class User.Model Extends (%RegisteredObject, %JSON.Adaptor)
{

Property Ident As %String;

Property PNG As %Stream.TmpBinary;

}

Class User.Data Extends %Persistent
{

Property Ident As %String;

Property PNG As %Stream.FileBinary;

Index Ident On Ident [ IdKey, Unique ];

Storage Default
{
<Data name="DataDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Ident</Value>
</Value>
<Value name="3">
<Value>PNG</Value>
</Value>
</Data>
<DataLocation>^User.DataD</DataLocation>
<DefaultData>DataDefaultData</DefaultData>
<IdLocation>^User.DataD</IdLocation>
<IndexLocation>^User.DataI</IndexLocation>
<StreamLocation>^User.DataS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

}