Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Joseph 59 posts 140 karma points
    Mar 18, 2015 @ 23:17
    Joseph
    0

    How do I programmatically change tags on an IContent?

    Hello

    I have been working on fixing a limitation in the Tag Manager package that I encountered in Umbraco 7 and encountered a weird behaviour with using IContentService to programatically save and publish content.

    To begin with; I'll try to quickly summarise the limitation that I found in the package; one of the features it offers is to merge tags - what it would do behind the scenes is to update the cmsTagRelationship table and change all references from one tag ID to another. What I found was that this change was not reflected in the tag property on the tagged content itself and so you get into a weird situation where the tag property is out of sync with the TagService backend.

    So I tracked down the piece of code which performs this merge and got cracking on trying to fix this:

        public int Save(cmsTags tag)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
    
            int success = db.Execute("Update cmsTags set tag = @0 where id = @1", tag.tag, tag.id);
    
            if (success == 1 && tag.id != tag.tagsInGroup.selectedItem.id)
            {
                string sqlQuery = string.Format("Update cmsTagRelationship SET tagID = {0} WHERE tagID = {1} AND nodeId NOT IN (SELECT nodeId FROM cmsTagRelationship WHERE tagId = {0});DELETE FROM cmsTagRelationship WHERE tagId = {1}", tag.tagsInGroup.selectedItem.id, tag.id);
    
                success = db.Execute(sqlQuery);
    
                // My code starts here
                foreach (var doc in tag.taggedDocuments)
                {
                    var content = UmbracoContext.Application.Services.ContentService.GetById(doc.DocumentId);
                    var tags = content.GetValue<string>("tags");
                    content.SetValue("tags", UpdateTags(tags, tag.tagsInGroup.selectedItem.tag, tag.tag));
                    UmbracoContext.Application.Services.ContentService.Save(content); // so far so good
                    UmbracoContext.Application.Services.ContentService.PublishWithStatus(content); // reverts the cmsTagRelationship change performed above
                }
                // My code ends here
            }
    
            return success;
    
        }
    

    (I realise that this is not the most generic fix i.e. given my use of a specific property alias for the tag property but bear with me at this point...)

    So the weirdness (as I've tried to indicate in the comments) is that while saving the changed content (via ContentService.Save) works as expected (at least for me); publishing the content (i.e. the next line) would undo the changes performed on the cmsTagRelationship table (i.e. the sqlQuery that was against the database). I have verified that the actual tagged content has its tag property updated as I would have expected; however we're still out of sync because the TagService backend change was reverted. Interestingly, re-running this operation synchronises everything up correctly.

    To illustrate this (hopefully more clearly):

    • Tagged content with tags taga, tagb
    • Use Tag Manager package to merge tagb to tagc
    • Tagged content's tags property now reads: taga,tagc but cmsTagRelationship table still refers that tagged content to taga and tagb
    • Use Tag Manager package to merge tagb to tagc again
    • Everything is now in sync

    At this point, my best guess is something other than the comma-delimited string in the tag property on the tagged content is updating the cmsTagRelationship table when IContentService.Publish (or any of its many variants) is invoked. I should also note here that manually publishing the content (i.e. by removing the PublishWithStatus line and then going to the content in the CMS and publishing the saved content) works as expected.

    Any ideas?

Please Sign in or register to post replies

Write your reply to:

Draft