Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validation does not allow empty Content in Binary (Hl7.Fhir.R5) #2806

Open
andrewrandallcaremetx opened this issue Jun 25, 2024 · 3 comments
Labels

Comments

@andrewrandallcaremetx
Copy link

Describe the bug
Generating a Bundle, including a Binary wrapped in an Entry, does not pass Validation. The Validation believes that Content should not be null. This requirement was true in R4, but should no longer apply in R5. Deserializing the message works correctly, but bundle.Validate(recurse: true) throws the following exception:

System.ComponentModel.DataAnnotations.ValidationException: Element 'ContentElement' with minimum cardinality 1 cannot be null. At Bundle.Entry.Resource.ContentElement, line , position
         at System.ComponentModel.DataAnnotations.Validator.ValidationError.ThrowValidationException()
         at System.ComponentModel.DataAnnotations.Validator.ValidateObject(Object instance, ValidationContext validationContext, Boolean validateAllProperties)
         at Hl7.Fhir.Validation.DotNetAttributeValidation.Validate(Object value, Boolean recurse, NarrativeValidationKind narrativeValidation)
         at Hl7.Fhir.Validation.DotNetAttributeValidation.Validate(Base value, Boolean recurse, NarrativeValidationKind narrativeValidation)

To Reproduce

using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
using Hl7.Fhir.Validation;
using System.Text.Json;
var bundle = new Bundle()
{
    Type = Bundle.BundleType.Message,
    Id = Guid.NewGuid().ToString(),
    Identifier = new Identifier
    {
        System = "example",
        Value = Guid.NewGuid().ToString(),
        Assigner = new ResourceReference
        {
            Display = "example"
        },
        Type = new CodeableConcept
        {
            Coding = [
                new Coding
                {
                    System = "http://terminology.hl7.org/CodeSystem/v2-0203",
                    Code = "RI",
                    Display = "Resource identifier"
                }
            ]
        }
    }
};

var list = new List()
{
    Id = Guid.NewGuid().ToString(),
    Status = List.ListStatus.Current,
    Mode = ListMode.Changes,
    Title = "messageContext"
};

var headerId = Guid.NewGuid().ToString();
bundle.Entry.Add(
    new Bundle.EntryComponent
    {
        FullUrl = $"urn:uuid:{headerId}",
        Resource = new MessageHeader
        {
            Id = headerId,
            Event = new Coding
            {
                System = "example",
                Display = "example"
            },
            Focus = new List<ResourceReference>
            {
                new ResourceReference
                {
                    Reference = $"urn:uuid:{list.Id}",
                    Type = "List"
                }
            },
            Source = new MessageHeader.MessageSourceComponent
            {
                Name = "example"
            }
        }
    });

bundle.Entry.Add(
    new Bundle.EntryComponent
    {
        FullUrl = $"urn:uuid:{list.Id}",
        Resource = list
    });

var binaryId = Guid.NewGuid().ToString();
var binaryEntry = new Bundle.EntryComponent
{
    FullUrl = $"urn:uuid:{binaryId}",
    Resource = new Binary
    {
        IdElement = new Id(binaryId),
        ContentType = "application/pdf"
    }
};
bundle.Entry.Add(binaryEntry);
list.Entry.Add(
    new List.EntryComponent
    {
        Item = new ResourceReference(binaryEntry.Resource.Id)
        {
            Type = binaryEntry.Resource.TypeName
        }
    });

var docRefId = Guid.NewGuid().ToString();
var docRefEntry = new Bundle.EntryComponent
{
    FullUrl = $"urn:uuid:{docRefId}",
    Resource = new DocumentReference
    {
        IdElement = new Id(docRefId),
        Status = DocumentReference.DocumentReferenceStatus.Current,
        Content = new List<DocumentReference.ContentComponent>
        {
            new DocumentReference.ContentComponent
            {
                Attachment = new Attachment
                {
                    Title = "file.pdf",
                    Url = $"s3://file.pdf"
                }
            }
        },
        Subject = new ResourceReference(binaryEntry.FullUrl)
        {
            Type = "Binary"
        }
    }
};
bundle.Entry.Add(docRefEntry);
list.Entry.Add(
    new List.EntryComponent
    {
        Item = new ResourceReference(docRefEntry.Resource.Id)
        {
            Type = docRefEntry.Resource.TypeName
        }
    });

var serializer = new FhirJsonSerializer(SerializerConfigs.FhirLib);
var bundleJson = serializer.SerializeToString(bundle);

var options = new JsonSerializerOptions().ForFhir(ModelInfo.ModelInspector);
var deserializedBundle = JsonSerializer.Deserialize<Bundle>(bundleJson, options);

bundle.Validate(true);

Expected behavior
.Validate(recurse: true) should not return any validation error.

Version used:

  • FHIR Version: R5
  • Nuget package <PackageReference Include="Hl7.Fhir.R5" Version="5.8.1" />
@danieldavis-caremetx
Copy link

danieldavis-caremetx commented Jun 25, 2024

It is worth noting that HL7.Fhir.Model.Binary defines the following:

/// <summary>
/// The actual content. Note: Element is replaced by 'Binary.data' since R4. Do not use this element 'content' with R4 and newer releases.
/// </summary>
[FhirElement("content", Order=70)]
[NotMapped(Since=FhirRelease.R4)]
[Cardinality(Min=1,Max=1)]
[DataMember]
public Hl7.Fhir.Model.Base64Binary ContentElement
{
  get { return _ContentElement; }
  set { _ContentElement = value; OnPropertyChanged("ContentElement"); }
}

Though ContentElement has been replaced since R4, Hl7.Fhir.Validation still appears to be validating its Cardinality attribute.

@mmsmits mmsmits added the bug label Jun 26, 2024
@ewoutkramer
Copy link
Member

Yeah, one more side-effect caused by the fact that we use two fields instead of one. See also #2786.

@ewoutkramer
Copy link
Member

Maybe add Since to the Cardinality attribute too? Or is that a hack for the deeper problem that only one of the two properties should be considered for validation (and deserialization) at any moment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Todo
Development

No branches or pull requests

4 participants