The OnTopic.Data.Transfer assembly defines a data transfer object to act as an intermediary between the Topic class and serialization targets (such as JSON) used for web services.
Technically, the Topic class—as well as its dependents—could be directly serialized. Because of the complexity of these classes, however, that would introduce a lot of clutter and complexity to the JSON format. This could be avoided, but would almost certainly require not only careful annotation of the entity classes, but quite possibly the introduction of custom converters. Further, even were this done, it wouldn't provide an opportunity to e.g. merge deserialized topics with an existing topic graph. Providing intermediary data transfer objects which offers a simplified data structure for modeling a topic, as well as extension methods for converting them to and from Topic classes addresses this problem.
The OnTopic.Data.Transfer assembly includes three basic data transfer classes along side a custom collection class:
TopicData: Maps to theTopicclass, and includes the following collections:Children(Collection<TopicData>)Attributes(KeyedCollection<String, RecordData>)RecordData: Maps to theTrackedRecord<T>class, and represents an individual attribute.
Relationships(MultiMap)KeyValuesPair: Maps to theKeyValuesPair<T>, and represents a relationship key, as well as a list of associations to related topics via theirTopic.GetUniqueKey()value.
References(KeyedCollection<String, RecordData>)RecordData: Maps to theTrackedRecord<T>class, and represents an individual topic reference.
The OnTopic.Data.Transfer.Interchange namespace includes extension methods for the OnTopic.Topic entity which allow a TopicData graph to be exported from a Topic graph—or imported back into one:
Topic.Export(): Exports a topic, and all child topics, into aTopicDatagraph.Topic.Import(): Imports aTopicDatagraph into an existingTopic, by default leaving preexisting attributes and relationships alone.
Optionally, the Topic.Export() extension method will accept an ExportOptions object as argument in order to fine-tune the business logic for the export. This includes the following options:
IncludeExternalAssociations: Enables associations—such as relationships and topic references—to be exported, even if the topics they point to fall outside the scope of the current export.IncludeNestedTopics: Includes nested topic as part of the export.IncludeChildTopics: Recursively includes all child topics—including nested topics—as part of the export. ImpliesIncludeNestedTopics.
Optionally, the Topic.Import() extension method will accept an ImportOptions object as argument in order to fine-tune the business logic for the import. Most notably, this includes a Strategy property for setting the ImportStrategy enum, which includes the following options:
Add: If aTopicexists, will only add new attributes to the object, while leaving existing attributes alone. This is the default.Merge: If aTopicexists, will only add newer attributes to the object, while leaving other attributes alone.Overwrite: If aTopicexists, will overwrite all attributes, even if the target attribute is newer.Replace: Will not only overwrite any matched attributes, but will additionally delete any unmatched topics, attributes, or relationships, thus ensuring the target object graph is identical to the sourceTopicDatagraph.
In addition to the Strategy property, the ImportOptions also allows the behavior to be fine-tuned, if further control is required:
DeleteUnmatchedAttributes: Determines if unmatched attributes should be deleted. Defaults tofalseunlessImportStrategy.Replaceis set.DeleteUnmatchedRelationships: Determines if unmatched relationships should be deleted. Defaults tofalseunlessImportStrategy.Replaceis set.DeleteUnmatchedReferences: Determines if unmatched topic references should be deleted. Defaults tofalseunlessImportStrategy.Replaceis set.DeleteUnmatchedChildren: Determines if unmatched children should be deleted. Defaults tofalseunlessImportStrategy.Replaceis set.DeleteUnmatchedNestedTopics: Determines if unmatched nested topics should be deleted. Defaults tofalseunlessImportStrategy.Replaceis set.OverwriteContentType: Determines if theContentTypeon an existingTopicshould be updated if theTopicDatavalue is different. Defaults tofalseunlessImportStrategyis set toOvewriteorReplace.
Finally, an import strategy can be defined for how to handle the LastModified and LastModifiedBy attributes during import by using the LastModifiedImportStrategy enum. This supports:
Inherit: Uses theImportStrategy.TargetValue: Always uses the value from the targetTopic, assuming the one exists.Current: Uses the current date forLastModifiedand current user forLastModifiedBy.System: Uses the current data forLastModifiedand the value "System" forLastModifiedBy.
When using a LastModifiedImportStrategy, there are three properties that should be defined on the ImportOptions object:
LastModifiedStrategyLastModifiedByStrategyCurrentUser(defaults to "System")
Serializing TopicData graphs to JSON and deserializing JSON back to a TopicData graph operates exactly like it would for any other C# objects.
var topicData = topic.Export();
var json = JsonSerializer.Serialize(topicData);
var topicData = JsonSerializer.Deserialize<TopicData>(json);
Installation can be performed by providing a <PackageReference /> to the OnTopic.Data.Transfer NuGet package.
<Project Sdk="Microsoft.NET.Sdk.Web">
…
<ItemGroup>
<PackageReference Include="OnTopic.Data.Transfer" Version="2.0.0" />
</ItemGroup>
</Project>Note: This package is currently only available on Ignia's private NuGet repository. For access, please contact Ignia.