FirelyTeam / firely-net-sdk

The official Firely .NET SDK for HL7 FHIR
Other
816 stars 340 forks source link

Binary resource returned from Update will throw a Null reference error trying to SerializeToXmlString #2786

Open brianpos opened 2 months ago

brianpos commented 2 months ago

Describe the bug When serializing a Binary resource to XML a Null reference is thrown. This is due to the children() function returning all the children without considering the version of fhir being processed. Data and Content hold the same data, but are apprpriate in different versions, and the ReadBinaryFataFromMessage in the HttpContentParsers sets both. https://github.com/FirelyTeam/firely-net-sdk/blob/963660e981550356d5535dad538aebec5e25e1da/src/Hl7.Fhir.Base/Rest/HttpContentParsers.cs#L203

Hence when hit in the PocoElementNode constructor the element definition for one of them isn't found and crashes.

Note: Create does not do this... as it doesn't detect that the resource type was for a Binary! (so create is done using the resource format rather than a binary stream)

To Reproduce Steps to reproduce the behavior:

        [TestMethod]
        public void SerializeBinaryXml()
        {
            // This test verifies that the serialization of a resource with changed between
            // fhir versions can be serialized correctly
            var binResource = new Binary
            {
                ContentType = "text/plain",
                // yes this is the wrong field for R4 (should use data there)
                Content = System.Text.Encoding.UTF8.GetBytes("some random content")
            };
            var xml = new FhirXmlSerializer().SerializeToString(binResource);
            // the above throws a null reference exception
            // once that passes probably want to actually check the content that came through
            // Assert.AreEqual(metaXml, xml);
        }

Use this unit test to check that the serialization doesn't throw the issue, but would be preferable if the update functionality doesn't set both fields

Better to udpate TestCreatingBinaryResourceHttpClient to also check the fields are appropriate

                var binary = new Binary() { Data = arr, ContentType = "image/png" };
                Assert.IsNull(binary.Content);
                var result = await client.CreateAsync(binary);
                Assert.IsNull(result.Content);

                var xml = new FhirXmlSerializer().SerializeToString(result);
                result = await client.UpdateAsync(result);
                Assert.IsNull(result.Content); // Fails here
                xml = new FhirXmlSerializer().SerializeToString(result); // or here due to the content being not null

Expected behavior Unit test should pass, and XML is created correctly.

Version used:

Additional context The only workaround is to request the resource response format in the client settings. clientFhir.Settings.BinaryReceivePreference = BinaryTransferBehaviour.UseResource;

ewoutkramer commented 1 month ago

The philosophical question is: "is a renamed property still the same property".

Another point to consider: when we add support for having unknown properties in resources (added to a dictionary, but not available via a code-generated property) in preparation of R6 ("allow unknown elements"), having properties that do not exist in that version's metadata will become more common.

No answers here, just a braindump of stuff to consider.

mmsmits commented 3 weeks ago

Decided that this for now is one property with two names:

Add:

    [FhirElement("content", Order=70, Since = FhirRelease.STU3)]
    [FhirElement("data", Order=70, Since = FhirRelease.R4)]    

On ContentElement.

The problem that remains is having to fix ITypedElementOnPoco. And probably others. Also check if the cardinality validator fetches the correct name when throwing errors.

Let's try and see what happens. Add [Obsolete] to the Content property.