Skip to content

v5.0.0

Compare
Choose a tag to compare
@JeremyCaney JeremyCaney released this 03 Mar 00:25
· 802 commits to master since this release

OnTopic 5.0.0 is a major release primarily focused on reliability and tidying up the interface. It includes a significant number of breaking changes—though only a handful of them will affect most implementers.

New Features

  • Metapackage: Established OnTopic.All metapackage which includes a reference to all of the core packages and implementations (c15bf2e).
  • SourceLink: Configured SourceLink with references to GitHub commits so that packages can be properly debugged by implementers (f7fb979).
  • IntelliSense: The NuGet packages now include the XML documentation, thus allowing implementers to benefit from IntelliSense annotations in Visual Studio (219ece4).
  • Lookup Fallback Types: Allow multiple fallback types to be defined when calling ITypeLookupService.Lookup() (ab4253d).
  • Topic References: Introduced support for keyed topic references via Topic.References, with full support for enforcing business logic (31144cc).
  • Full Versioning Support: Introduced versioning support for Relationships and TopicReferences, in addition to the previous support for versioning in Attributes and ExtendedAttributes (0e808ea).
  • Repository Caching: Established a ITopicRepository.Refresh() interface (3d51b14), SqlTopicRepository.Refresh() implementation (6dbf973), as well as a GetTopicUpdates stored procedure (0f36947) to allow occasional cache updates without needing to reload the entire topic graph (164de05).
  • Contextual Loading: When calling ITopicRepository.Load(), an optional referenceTopic can now be passed; this allows individual topics or topic branches to be loaded, while still being able to connect relationships and topic references to elsewhere in the topic graph (180526e). It can also be used to update topics already in the topic graph.
  • Resolve Associations: TopicRepository.Save() will now recurse over Children and attempt to resolve unresolved associations, such as relationships and topic references (fdd0025, e703de5); previously, this had to be implemented by each individual implementation.
  • Repository Events: ITopicRepository now supports the TopicLoaded and TopicSaved events, in addition to the previous TopicRenamed, TopicMoved and TopicDeleted events (37b38f5).
  • C# 9.0 Records: Introduced support for mapping C# 9.0 records with init setters in the topic mapping services (75dea66, 145c2a4) and updated all view models and binding models from read/write classes to C#'s new read-only, immutable record types (10d0652).
  • Core Attributes: TopicKey, ContentType, and ParentID are now first-class columns in the Topics table (c50f44d), greatly simplifying querying for the core attributes.
  • SQL Unit Tests: Introduced unit tests for stored procedures and functions for SQL Server database schema (91e3fe4) as well as for the SqlDataReader extension methods used by SqlTopicRepository (b91c292), thus offering far more assurances over the correctness and regression testing.

Bug Fixes

  • Post-Exception Business Logic Enforcement: If an exception occurs while enforcing business logic on Topic.Attributes, the request will be de-registered, thus ensuring any subsequent attempts to set an item with the same key will have business logic enforced (1b5dd5b). Previously, the exception could prevent that process from being completed, thus introducing a potential loophole during subsequent actions.
  • Track Deleted Attributes: Ensured that AttributeCollection.Clear() correctly marked the collection as IsDirty(), if appropriate, by accounting any DeletedAttributes (ce3cc43).
  • Track Attribute Reversions: Ensured that all modified AttributeRecord instances in a TopicRepositoryBase.Rollback() operation were correctly marked as IsDirty, thus ensuring they would be properly Save()d (e77d8eb).
  • Allow Duplicate Topic Keys in Relationships: The Topic.Relationships collection now allows relationships to different topics with the same Topic.Key (66ccd9d). Previously, this used a KeyedTopicCollection, which artificially restricted it to relationships with a unique Key.
  • Allow Duplication Topic Keys in FindAll(): Fixed a bug in the Topic.FindAll() extension methods which prevented it from returning multiple topics which the same Key, even if they represented different entities (75f6369).
  • Track Version in Reversion: Fixed bug in the GetTopicVersion stored procedure which resulted in the Version column not being returned for Attributes or ExtendedAttributes, and thus the AttributeRecord.LastModified not being properly updated during e.g. a Rollback() (622d575). In practice, this didn't harm anything, but it prevented removal of legacy schema validation which explicitly looked for the Version column.
  • Map Overriden Members and Overloaded Methods: Resolved an issue where the MemberInfoCollection<T>—used by the topic mapping services—would throw an exception if an overloaded or overridden member was present on a type (75dea66). Now, it will simply defer to the first or most derived instance of a member, and ignore all others. This enables support for C# 9.0 records, which have an implicit compiler-injected override, and is also a logical default for most scenarios where this might occur.
  • Allow Multiple Roots: Fixed bug where calling the CreateTopic or MoveTopic stored procedures with a null @ParentID would result in a corrupted hierarchy (500ca09). This isn't an expected use case, but we obviously want to make sure there's no risk of corrupting the hierarchy if it does occur.
  • Stored Procedure Errors: Fixed the RAISERROR() calls in the MoveTopic stored procedure; these weren't working correctly due to a formatting bug (bfdec1c).

Breaking changes

For a quick summary of all renamed and removed types, members, and methods, see #27.

  • .NET Framework Support: Removed support for .NET Standard 2.0 and, thus, .NET Framework; this effectively ends support for OnTopic-WebForms, OnTopic-MVC, and OnTopic-Editor-WebForms (b3ba1a0).
  • Topic.DerivedTopic: Renamed Topic.DerivedTopic to the more semantically accurate Topic.BaseTopic (2486ab2). This breaks not only calls to Topic.DerivedTopic, but also database records for e.g. ReferenceKeys storing the DerivedTopic value. The OnTopic 5.x database migration script addresses the data aspects of the migrations.
  • Immutable View Models: Changed all view models and binding models from read/write classes to C#'s new read-only, immutable record types (10d0652). This necessitates that all adopters that rely on these migrate any derived types from classes to records.
  • Keyed Topic Collections: Renamed TopicCollection classes (such as TopicCollection<T>, ReadOnlyTopicCollection) to KeyedTopicCollection (e.g., KeyedTopicCollection<T>, ReadOnlyKeyedTopicCollection) to better communicate that the items are indexed and, thus, must have a unique key, even if they represent different entities (826b93c).
  • Attribute Collection: Renamed AttributeValueCollection to AttributeCollection, and AttributeValue to AttributeRecord (f51407a).
  • TopicRelationshipMultiMap: The RelatedTopicCollection and NamedTopicCollection used by Topic.Relationships have been replaced with TopicRelationshipMultiMap (57ff3f9, 7129289), ReadOnlyTopicMultiMap (eb5c1c3), and TopicMultiMap (d049ea9). Care was taken to maintain the overall interface. The interface for calls to the underlying collections, however, will have changed (66ccd9d). Most notably, all write operations must now go through SetValue(), Remove(), or Clear(). In addition, for callers iterating over the relationships, the relationship key is now Key not Name, the topics are now stored under a Values property, and the methods now require a full Topic reference, instead of just a Topic.Key (0d9dcd5).
  • GetValue() Syntax: Renamed (ReadOnly)KeyedTopicCollection<T>.GetTopic() to GetValue() (6674c7d); on TopicRelationshipMultiMap (i.e., Topic.Relationships), renamed GetAllTopics(), GetTopics(), RemoveTopic(), and ClearTopics() to GetAllValues(), GetValues(), Remove(), and Clear() for consistency with other collections, and especially the TrackedRecordCollection used by AttributeCollection and TopicRelationshipCollection (34a8c52).
  • OnTopic.Lookup namespace: Consolidated all ITypeLookupService implementations into a new OnTopic.Lookup namespace (f80e084).
  • Load() by Unique Key: Modified Load(topicKey) to instead expect a fully-qualified UniqueKey (e.g., Root:Web:Products); as part of that, renamed the topicKey parameter to uniqueKey to disambiguate usage (4c3d30f).
  • Mapping Attributes: Renamed [Relationship()] to [Collection()] (f84ae66), [Follow()] to [Include()] (7c150d8), RelationshipType to CollectionType (1daf799), and Relationships to AssociationTypes (78600fd) as part of a broader effort to establish a more consistent and unified nomenclature that distinguishes between topic associations and specific types of associations, such as Topic.Relationships, Topic.References, or Topic.BaseTopic (b01216e).
  • Filter by Content Type: The [FilterByAttribute()] attribute continues to operate as it previously did, but can no longer be used to filter by ContentType since content type is no longer stored in Topic.Attributes (4a9f5b7); instead, use the new [FilterByContentType()] attribute (105cfdd). If ContentType is used with [FilterByAttribute()], an ArgumentException will be thrown (c68040a).
  • IRouteBuilder Support: Removed (deprecated) support for IRouteBuilder extension methods in ASP.NET Core; implementers should use end point routing via IEndpointRouteBuilder instead (6be993b, 19612ac).
  • NavigationViewModel: Replaced CurrentKey with CurrentWebPath; updated the INavigationTopicViewModel<T>'s IsSelected() method to expect a webPath parameter instead of a uniqueKey parameter (3e68b16).
  • Core Attributes: Added @Key and @ContentType to the CreateTopic and UpdateTopic stored procedures (a74389d); removed TopicKey, ContentType, and ParentID from the Attributes table; they are now in the Topics table (c50f44d).

Improvements

  • Default Attribute Values: The AttributeCollection extension methods, such as GetBoolean() and GetDateTime(), no longer require that a defaultValue parameter be defined; if it is omitted, the default value for each datatype (e.g., false for GetBoolean) will be used (a79a0b1).
  • TrackedRecordCollection<>: Established new TrackedRecordCollection<> and base TrackedCollection<> to handle IsDirty tracking and enforcement of business logic in keyed collections associated with a particular topic; this is now the base class for both AttributeCollection and TopicReferenceCollection (8b9ae46).
  • Topic.IsDirty(): Introduced Topic.IsDirty() method to aid in state tracking; optionally, this can optionally call AttributeCollection.IsDirty() and RelatedTopicCollection.IsDirty() via the checkCollections parameter (a8feb6d, f7d36f0).
  • Topic.MarkClean(): Introduced MarkClean() method to Topic (28ea6ea, 48e8ed4) and RelatedTopicCollection (c37934b).
  • ITrackDirtyKeys: Introduced a new ITrackDirtyKeys interface to standardize the implementation of IsDirty() and MarkClean() between Topic (f7d36f0), Topic.Attributes, Topic.Relationships, and Topic.References (c757dd3).

The above is just a high-level summary of the highest impact features, changes, and improvements. For complete release notes, see Pull Request #28.