Releases: OnTopicCMS/OnTopic-Library
v5.2.0
OnTopic 5.2.0 introduces support for response caching (#89), a new ErrorController for HTTP error codes (#91), and improvements to ITopicMappingService performance via optional AttributeDictionary constructors (#99), updates to the internal reflection libraries (#90), and caching of compatible properties (#102). In addition, it also includes a number of internal code improvements, such as adoption of new C# 10 capabilities (#96), including global using directives (#93).
Features
- #89 Response caching is now supported on
TopicController, via OnTopic support for cache profiles - #91 (Re)introduced an
ErrorControllerto fully handle HTTP error handling within ASP.NET Core - #99 Support for
AttributeDictionaryconstructors on view models to improve performance ofITopicMappingService
Improvements
- #90 Improved performance in reflection by use of
Delegate.CreateDelegate() - #90 Significant refactoring of the
OnTopic.Internal.Reflectionclasses around theTypeAccessor(Cache), instead of(Type)MemberInfoCollection(reference) - #101 Allow the
ErrorControllerto be bypassed for static files, thus preferring a lightweight response code instead of a friendly error page - #102 Cache mappings to compatible members on corresponding
Topicclasses (e.g.,ContentTypeDescriptor) viaMemberAccessor.IsCompatible() - #106 Add a SQL constraint to ensure that topics under a given parent topic can't have duplicate keys
For a comprehensive list of features, improvements, and code changes, see Pull Request #108.
v5.1.0
OnTopic 5.1.0 is a minor release which introduces support for mapping constructor parameters (#35) and defining what model to use when mapping associations via the [MapAs()] attribute (#41). Primarily, however, it is focused on bug fixes, and resolves a number of priority issues.
Features
- #37 Reference configuration posted to OnTopic-Schema
- #41
[MapAs()]attribute for specifying the mapping type of a property or collection - #35 Map constructor parameters
Improvements
- #83
TopicMappingService: Proactively check type compatibility - #72
Sitemap: Exclude Private or System Branches withIsProtected - #77 Validate
!IsNewonTopicRepositorymethods - #42
ReverseTopicMappingService: Overwrite existing topic references
Bugs
- #47
Delete()throws exception if topic references are present - #46
Load()treats deleted references as unresolved - #76 Unable to move first child after a sibling
- #53 Existing Topics w/
ParentmarkedIsDirty() - #73 Implicitly
IsDirty()topics not being saved - #86 Versions getting saved even if no attributes have been modified
- #71 Null values overwrite initialized defaults
- #38, #52
IncomingRelationshipsare not being removed fromTopicReferenceCollection.Clear()orSetValue()w/null - #79
Remove()andClear()offer a backdoor toenforceBusinessLogic - #50
TopicRenamedevent not being raised - #75, #88 Factor associations into
ConsolidateVersions,DeleteOrphanedLastModifiedAttributes - #78
VersionHistoryIndexshould account for all versioned tables, not justAttributes - #60, #61 Prioritize area views over regular views, and fall back
- #61 Views should fall back to using the controller action, if available
- #63
TopicViewResultExecutorfails if there are multiple HTTP Accept Header values
For a comprehensive list of bug fixes and improvements, see Pull Request #85.
v5.0.0
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.Allmetapackage which includes a reference to all of the core packages and implementations (c15bf2e). - SourceLink: Configured
SourceLinkwith 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
RelationshipsandTopicReferences, in addition to the previous support for versioning inAttributesandExtendedAttributes(0e808ea). - Repository Caching: Established a
ITopicRepository.Refresh()interface (3d51b14),SqlTopicRepository.Refresh()implementation (6dbf973), as well as aGetTopicUpdatesstored procedure (0f36947) to allow occasional cache updates without needing to reload the entire topic graph (164de05). - Contextual Loading: When calling
ITopicRepository.Load(), an optionalreferenceTopiccan 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 overChildrenand 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:
ITopicRepositorynow supports theTopicLoadedandTopicSavedevents, in addition to the previousTopicRenamed,TopicMovedandTopicDeletedevents (37b38f5). - C# 9.0 Records: Introduced support for mapping C# 9.0 records with
initsetters 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, immutablerecordtypes (10d0652). - Core Attributes:
TopicKey,ContentType, andParentIDare now first-class columns in theTopicstable (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
SqlDataReaderextension methods used bySqlTopicRepository(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 asIsDirty(), if appropriate, by accounting anyDeletedAttributes(ce3cc43). - Track Attribute Reversions: Ensured that all modified
AttributeRecordinstances in aTopicRepositoryBase.Rollback()operation were correctly marked asIsDirty, thus ensuring they would be properlySave()d (e77d8eb). - Allow Duplicate Topic Keys in Relationships: The
Topic.Relationshipscollection now allows relationships to different topics with the sameTopic.Key(66ccd9d). Previously, this used aKeyedTopicCollection, which artificially restricted it to relationships with a uniqueKey. - Allow Duplication Topic Keys in
FindAll(): Fixed a bug in theTopic.FindAll()extension methods which prevented it from returning multiple topics which the sameKey, even if they represented different entities (75f6369). - Track Version in Reversion: Fixed bug in the
GetTopicVersionstored procedure which resulted in theVersioncolumn not being returned forAttributesorExtendedAttributes, and thus theAttributeRecord.LastModifiednot being properly updated during e.g. aRollback()(622d575). In practice, this didn't harm anything, but it prevented removal of legacy schema validation which explicitly looked for theVersioncolumn. - 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
CreateTopicorMoveTopicstored procedures with anull@ParentIDwould 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 theMoveTopicstored 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: RenamedTopic.DerivedTopicto the more semantically accurateTopic.BaseTopic(2486ab2). This breaks not only calls toTopic.DerivedTopic, but also database records for e.g.ReferenceKeys storing theDerivedTopicvalue. 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
recordtypes (10d0652). This necessitates that all adopters that rely on these migrate any derived types from classes to records. - Keyed Topic Collections: Renamed
TopicCollectionclasses (such asTopicCollection<T>,ReadOnlyTopicCollection) toKeyedTopicCollection(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
AttributeValueCollectiontoAttributeCollection, andAttributeValuetoAttributeRecord(f51407a). TopicRelationshipMultiMap: TheRelatedTopicCollectionandNamedTopicCollectionused byTopic.Relationshipshave been replaced withTopicRelationshipMultiMap(57ff3f9, 7129289),ReadOnlyTopicMultiMap(eb5c1c3), andTopicMultiMap(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 throughSetValue(),Remove(), orClear(). In addition, for callers iterating over the relationships, the relationship key is nowKeynotName, the topics are now stored under aValuesproperty, and the methods now require a fullTopicreference, instead of just aTopic.Key(0d9dcd5).GetValue()Syntax: Renamed(ReadOnly)KeyedTopicCollection<T>.GetTopic()toGetValue()(6674c7d); onTopicRelationshipMultiMap(i.e.,Topic.Relationships), renamedGetAllTopics(),GetTopics(),RemoveTopic(), andClearTopics()toGetAllValues(),GetValues(),Remove(), andClear()for consistency with other collections, and especially theTrackedRecordCollectionused byAttributeCollectionandTopicRelationshipCollection(34a8c52).OnTopic.Lookupnamespace: Consolidated allITypeLookupServiceimplementations into a newOnTopic.Lookupnamespace (f80e084).Load()by Unique Key: ModifiedLoad(topicKey)to instead expect a fully-qualifiedUniqueKey(e.g.,Root:Web:Products); as part of that, renamed thetopicKeyparameter touniqueKeyto disambiguate usage (4c3d30f).- Mapping Attributes: Renamed
[Relationship()]to[Collection()](f84ae66),[Follow()]to[Include()](7c150d8),RelationshipTypetoCollectionType(1daf799), andRelationshipstoAssociationTypes(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 asTopic.Relationships,Topic.References, orTopic.BaseTopic(b01216e). - Filter by Content Type: The
[FilterByAttribute()]attribute continues to operate as it previously did, but can no longer be used to filter byContentTypesince content type is no longer stored inTopic.Attributes(4a9f5b7); instead, use the new[FilterByContentType()]attribute (105cfdd). IfContentTypeis used with[FilterByAttribute()], anArgumentExceptionwill be thrown (c68040a). IRouteBuilderSupport: Removed (deprecated) support forIRouteBuilderextension methods in ASP.NET Core; implementers should use end point routing viaIEndpointRouteBuilderinstead (6be993b, 19612ac).- **`Navigat...
v4.6.0
OnTopic 4.6.0 includes a few minor features, most notably improvements over routing and reporting for the ASP.NET Core TopicController. In addition, it upgrades the underlying code to C# 9.0 in order to take advantage of some new capabilities such as improved pattern matching and implicitly typed initializers.
Features
- Updated
[ValidateTopic]attribute to redirect to canonical URL to ensure consistency in analytics, indexes (0edab34) - Updated
Topic.Load(RouteData)extension to return null if an invalidKeyis submitted (b303f13); this results in theTopicControllertreating incorrect topic paths (e.g.,/Web/!@~/) as 404s instead of exceptions - Added support for enabling (
IsIndexed) and configuring (IndexLabel) an optional table of contents to theContentListTopicViewModel(e9ccb06)
Bug Fixes
- Fixed issue with where the delegate is validated in the
HierarchicalTopicMappingService.GetViewModelAsnc()method (69dff49)
Improvements
- Updated code to use C# 9.0 pattern matching and implicitly typed initializers (d63f2b5)
- Updated to latest versions of internal packages, and implemented (4838da8)
- Updated to latest version of Code Analysis and fixed most issues introduced with C# 9.0 (089c96a)
Note: There are some Code Analysis false positives that remain with C# 9.0. Those are presumably fixed with the new
Microsoft.CodeAnalysis.NetAnalyzers5.0.0. There appears to be a bug in getting that to work with .NET 3.x projects, however, so it's not yet implemented. That will be revisited in a future release.
v4.5.0
This update focuses primarily on minor feature improvements, such as new extension methods for Topic (7d08ac6) and AttributeValueCollection (9795dd1), as well as new utility functions in the SQL schema (1e9b1d5), such as GetUniqueKey() (a2ac659) and GetTopicIDByUniqueKey() (ea97f91). It also includes a number of bug fixes as well as some cleanup. Most notably, it fixes a bug where existing attributes values cannot be reset to empty under certain circumstances—notably include those involving the OnTopic Editor (1e4812f).
Features and Improvements
- Added
MarkClean()methods toAttributeValueCollectionto improve the semantics forIsDirtytracking and to better account for deleted attributes (1e4812f) - Added
FindAll()(4dbf872),FindFirstParent()(aa54ccf), andGetContentTypeDescriptor()(026e7a3) extension methods forTopic(7d08ac6) - Added
GetDouble()(148a1b1) andSetDouble()(23f9ce2) extension methods toAttributeValueCollection(9795dd1) - Added
GetChildTopicIDs()(8e0eca5) andFindTopicIDs()(1dfd333) functions in order to facilitate tree traversal and lookups in SQL - Added
GetUniqueKey()(a2ac659),GetTopicIDByUniqueKey()(ea97f91), andGetExtendedAttribute()(28a4694) functions, as well as aUniqueKeyIndexview (b09ca5d) to the SQL database schema (1e9b1d5) - Added and implemented (68492d2) the
AddOrReplace()(cd92791) andTryAdd()(027ae25) methods to theStaticTypeLookupServiceto simplify inheritance (6687431) - Significant updates to
GenerateNestedSetto support transactions and topic ordering, while eliminating the need forTopics.RangeRightto allowNULL(c6b50f3)
Bug Fixes
- Fixed a bug where a deleted attribute might not get saved since deleted attributes didn't result in the
AttributeValueCollectionbeing marked asIsDirty()(1e4812f) - Updated
GetAttributes()stored procedure as a function (aa040ef) to return the latest version of both indexed and extended attributes (05ae378) - Used UTC time for
@Versionparameter when updating the database viaSqlTopicRepository.Save()to avoid time mismatches between computers (d85743d) - Updated
RelatedTopicCollection.RemoveTopic()to remove reciprocalIncomingRelationshipsin order to avoid stale content or orphaned references (4514244) - Improved validation for
TopicRepositoryBase.Delete()(67b70ca), including checks forisRecursivemismatches (29c904a) and orphanedDerivedTopics (58057e1), as well as handling of orphaned relationships (13e4fe9, 2550779)
Cleanup
- Cleanup of SQL objects (c997b0e), including moving
UniqueKeyIndex(4a17205),LeftRightRange(e565f0e), andHierarchy(nowAdjacencyList) to theUtilitiesschema (17b98b4), and removal of legacySimpleIntListToTblandSplitfunctions (f0e781b). - Applied updates based on new code analysis warnings (b00cfad)
Potentially Breaking Changes
- Moving, renaming, and deleting of utility objects in SQL database schema (c997b0e)
- Setting default for
ITopicRepositoryBase.Delete()'sisRecursiveparameter fromfalsetotrueto maintain backward compatibility (1773113)
Note: These aren't expected to break any actual implementations. In particular, utility objects are not referenced from the products, and most weren't previously documented, so it's not expected that they would have been integrated with or called from third-party implementations. Similarly, while the change to
ITopicRepositoryBase.Delete()changes the default, it does so to avoid a behavioral change.
v4.4.0
This update primarily focuses on introducing new extension methods for registering topic areas (66c53c9). In addition, it also shores up the implementation of Oroborus Configuration, helping ensure that updates to ContentTypeDescriptor and AttributeDescriptor instances are reflected immediately in e.g. the OnTopic Editor. These were caused by version conflicts introduced by multiple in-memory instances of the same topic entities stored in e.g., TopicRepositoryBase._contentTypeDescriptors and CachedTopicRepository._cache (85216c4). Finally, this separates out the verbose sitemap into an Extended() action—which includes all relationships and attribute metadata; the default Index() now outputs a shorter form sitemap, based on the data most search agents utilize (86df229).
Features
- Introduced a series of extension methods for configuring topic areas—including
MapTopicAreaRoute(),MapDefaultAreaControllerRoute(), andMapImplicitAreaControllerRoute()(66c53c9) - Introduced a new
Extended()action onSitemapControllerto display extended metadata, while setting the defaultIndex()action to display a standard—and much smaller—sitemap (86df229) - Containers are used to organize topics, but aren't intended to be displayed to users. They are now hidden from the Sitemap (87b6d1b) and will return a 403 Unauthorized if accessed (e4130cf)
Improvements
- Significantly improved real-time updates of Oroborus Configuration via OnTopic by introducing code to centralize references of
GetContentTypeDescriptors()in order to avoid version conflicts with e.g.CachedTopicRepository(85216c4) - Extended the search criteria for mapping routing variables to topic paths in order to support implicit controllers (74a8a76)
- Implementing .NET Core 3.x's
{**path}catch-all route handling for thepathvariable, ensuring it is not encoded (30c6691)
Maintenance
- Updated development and build dependencies in NuGet (21a9ad7)
v4.3.0
This update provides backend functionality and bug fixes to improve performance and reliability, with a particular emphasis on importing and saving large topic graphs. The OnTopic library can now connect to empty databases, and persist in-memory topic graphs to them. To do this, it dynamically identifies content type and attribute descriptors from that topic graph. Further, when recursively saving topic graphs, there are significant performance improvements—while simultaneously fixing bugs that can occur when there are mismatches between the configuration of the saved and in-memory schemas.
Functionality
ContentTypeDescriptors (a9ea634) andAttributeDescriptors (b0c5a5e) are now updated dynamically when saved, and thus configuration changes are now available immediately without requiring an application restart (fb3366e).- The byline (
LastModifiedBy) and dateline (LastModified) are now only persisted to the underlying topic repository if any other attributes (d8d41b7) or relationships (8caa148) have changed (d8d41b7). - Arbitrary attributes (i.e., attributes not defined in the
ContentTypeDescriptor) can now be programmatically added (c3c01ef), modified, or deleted (2151a08) via the OnTopic Library (8b7dffe). - Empty databases can now be connected to without throwing exceptions, thus allowing a reference schema can be
Import()ed via the OnTopic Data Transfer library using the OnTopic Editor (695664d). TopicRepository.Save()will now loop back and save any topics with previously unresolved (i.e., unsaved) references (including relationships orDerivedTopic) (913b68d).UpdateRelationshipsnow synchronizes relationships, instead of just inserting them. It accepts an optional@DeleteUnmatchedargument which can be disabled to append new relationships, instead of also deleting unmatched relationships (cbba817).
Bug Fixes
- Fixed a bug where topics from the previous relationship were saved to each subsequent relationship for a topic (27d9bfe).
- Fixed a bug where attributes that had been reconfigured away from
IsIndexedAttribute, but not otherwise changed, would be orphaned (7a61005) deleted (d64d242) onSave(). - Fixed a bug where an off-target exception would be thrown if
SqlTopicRepository.Load(string topicKey)wasn't able to identify a matching topic (c97dcb3). - Fixed a bug where unsaved relationships (6da3fa4) and derived topics (a3b6da1) were saving
-1to the database if they referenced unsaved topics.
Code Changes
Performance
- Reduced execution time of
UpdateTopicby 50% through optimization of queries (fae0e8d). SqlTopicRepository.Save()will only save topics which have actually changed; this greatly increases the performance of recursive saves when merging large topic graphs (afa1e9b).
API Changes
- Introduced
AttributeValuesDataTable(313fe71) andTopicListDataTable(7a37dc9) to encapsulate the corresponding user-defined, table-valued types in SQL, and extendedSqlCommand.AddParameter()to support them (0cd2506). - Introduced
TopicNotFoundException(2300e69), which derives fromTopicRepositoryExceptionand is used inITopicRepository.Load(). - Introduced
TopicRepositoryBase.GetContentTypeDescriptor()convenience method (408d01a) for loading aContentTypeDescriptor—either from the database, or from the local topic graph. - Introduced
TopicRepositoryBase.GetAttributes()method for retrieving extended or indexed attributes, optionally filtered byIsDirty(120c55e). - Introduced
Topic.GetTopicByUniqueKey()(867b110) andTopic.GetRootTopic()(0bddfb0) extension methods toOnTopic.Queryablenamespace (d18984d). - Introduced
Topic.IsNewproperty for tracking whether a topic is new, or if it has been persisted to the database (1678523, f046179). - Introduced a
NamedTopicCollection.IsDirtyproperty (4762694),RelatedTopicCollection.IsDirty()(2adef58), andAttributeValueCollection.IsDirty()(d3b49ff) for tracking if any relationships or attributes have changed (afa1e9b). - Removed legacy
SqlTopicRepository.CreateRelationshipsXml()private helper function, as that functionality is no longer used (7bea7d3).
General
- Migrated to C# 8.0's new block-level
usingstatement, in favor of placing explicitDispose()calls infinallyblocks (f85aab2) - Migrated to GitVersion's
ContinuousDeploymentmode for all branches exceptmasterto simplify version incrementing on feature branches (b4105f3).
Maintenance
v4.2.0
The 4.2.0 release includes backend refactoring, new maintenance scripts for database administrators, a bug fix for versioning, and some new deprecation warnings in anticipation of future updates.
New Features
Database Scripts
- Moved maintenance-oriented stored procedures to a new
[Utilities]schema (402301f). - Officially documented maintenance-oriented stored procedures (2df59ad).
- Introduced new stored procedures for reducing extraneous records and old versions stored in the SQL database:
DeleteConsecutiveAttributesDeleteConsecutiveExtendedAttributesConsolidateVersionDeleteOrphanedLastModifiedAttributes
Note: With the exception of
ConsolidateVersions, these new procedures are "lossless", meaning they compress the data without losing any historical versioning information.
Code Changes
OnTopic.Data.Sql
- Much of the topic loading code was moved to the new
SqlReaderExtensions(7ca6c0e). - Helper methods for creating parameters have been moved to a set of extension methods in the new
SqlCommandExtensionsclass (7ca6c0e).
Note: These changes don't have any impact on the public API; they just makes the code itself more maintainable and easier to read.
Deprecation Notices
While OnTopic 5.0 hasn't been planned out yet, we have identified a few parts of the public API which will be deprecated. In anticipation of that, deprecation warnings have been implemented on those classes and members (b49ce5e). Most of these aren't being used by any implementors, and shouldn't cause problems. These include:
- All
ITopicRepositoryevents, such asDeleteEvent,RenameEvent, andMoveEvent - A couple of
Topicconvenience accessors for retrieving attributes, includingViewandDescription - Members of classes such as some helpers in
SitemapControllerwhich should have been marked asprivatewhen they were introduced
Bug Fixes
- Topic versions are now created using a lower precision so that they match the exact value in the database (90c83d4). This fixes a bug which prevented rolling back to versions created since the last application reset.
v4.1.1
v4.1.0
The 4.1.0 release introduces bug fixes for the SitemapController, transaction support for certain database operations, unified support between TopicMappingService and ReverseTopicMappingService, as well as an update to how AttributeValue objects are created in order to supports merging topics.
New Features
- The
SitemapControllernow compresses the XML output by default (6a5f671). This can optionally be disabled by calling it with?Indent=true. - The
SqlTopicRepositorynow retrieves the preciseVersionfor each attribute, and sets that value to theAttributeValueobject (a83b844). This enables support for merging topics based on timestamp as part of the new OnTopic-Data-Transfer library. - The
TopicMappingServicenow supports new attributes originally introduced forReverseTopicMappingService(8e56be8). Notably, this includes support for[MapToParent]and[DisableMapping]. Critically,[MapToParent]allows attributes from a topic to be mapped to complex object types used for view model properties.. - The
MoveTopicandDeleteTopicstored procedures now implement table locks and transactions to prevent potential database corruption issues during concurrent updates (a16ea48). While a rare scenario, the potential consequences are sever. - The database project now includes a new
ValidateHierarchystored procedure (a16ea48), which allows the nested set hierarchy to be validated to ensure that no corruption has taken place.
Bug Fixes
- The
SitemapControllernow renders the output asUTF-8not the default ofUTF-16(32e8289). This maintains compatibility with the Sitemap.org specification which mandatesUTF-8.
Maintenance
- Most NuGet package dependencies have either been removed or marked as
<PrivateAssets />(87b3034). This reduces the number of dependencies carried forward to downstream consumers.