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.
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:
(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):
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?
is working on a reply...