Why does Sitecore publish draft items from the C# API, and how do I stop it doing so?
Asked Answered
C

2

9

I'm running a scheduled publish of my Sitecore master DB using the Sitecore publishing API. I call a web service at scheduled intervals during the day which runs the following code (slightly condensed for readability):

// grab the root content node from sitecore
Item contentNode = dbSource.Items[ID.Parse("{0DE95AE4-41AB-4D01-9EB0-67441B7C2450}")];

PublishOptions options = new PublishOptions(sourceDatabase, targetDatabase, PublishMode.Smart, lang, DateTime.Now);

options.RootItem = contentNode;

options.Deep = true;

Publisher p = new Publisher(options);

p.PublishAsync();

When we run the above code it publishes everything in the content node, including all descendants, regardless of workflow state. It's like it is ignoring the workflow completely. This is not what we are after, and is causing lots of problems on our live website.

If we run the same action from within Sitecore Desktop it publishes everything in the content node, including all descendants, that are publishable (I.e. in the final workflow stage). It does not publish any items in the tree that are still in draft mode. This is the required bahaviour.

I have tried implementing the code as a non-admin user by surrounding the above code with the following using statement:

string userName = @"sitecore\******";

Sitecore.Security.Accounts.User user = Sitecore.Security.Accounts.User.FromName(userName, true);

user.RuntimeSettings.IsAdministrator = false;

using (new Sitecore.Security.Accounts.UserSwitcher(user))
{
    ...
}

Unfortunately this has had no effect.

Is there something obvious I've missed, or am I doing it right and Sitecore is doing it wrong? Can anyone help please?

The strange thing I noticed, also, is that the draft items that were published, when viewed on the live database, were showing absolutely nothing in the Sitecore Desktop in terms of fields or meta data. They were also showing a warning that "The current item does not have a version in "English : English".

Cockshy answered 5/9, 2012 at 15:41 Comment(2)
You don't need service for this. Sitecore has it's own scheduler.Carom
Thanks @horseman, but I think the Sitecore built in scheduler works on an interval, which can easily reset when the ASP.NET AppPool recycles. This can and will mess up any proper schedules you may have for publishing. As a result, we use a web service which is called on a schedule from the Windows Task Scheduler.Cockshy
C
4

TL;DR Root content node had version in another language, removing that version, or only publishing in English language prevented publishing of items in draft mode

OK, so after trying @techphoria414's suggested code, it became clear that the context wasn't the issue. The publisher WAS adhering to workflow after all, but the problem has turned out to be the root content node having a version in another language (Japanese - don't ask me how this got there), but the descendant nodes having no versions in Japanese at all. In fact, our master database is only configured to have English as a language so it shouldn't even be possible for a user other than admin to add a version in another language.

I have conducted some tests and found that the publisher ignores workflow for items that exist in another language. Consider the following scenario:

1) You add a folder and any item underneath ("test workflow item") which has workflow. Don't commit the item, leaving it at version 1, in draft mode (i.e. shouldn't be publishable). The containing folder only has one version in one language (English):

You add a folder and any item underneath which has workflow Folder has english version only

2) You publish the folder with a deep publish to your web db (using the code in my question). This results in the following (folder added, but draft "test workflow item" not added). This is expected behaviour - yay!

You publish the folder with a deep publish

3) Add a new version to the containing folder in a different language.

Add a new version to the containing folder in a different language

4) Check the workflow state of the child item now that Japanese is selected as the language. Notice, in the gutter it no longer says it is in draft mode, but there is no version at all in Japanese (as seen to the right).

Check the workflow state of the child item now that Japanese is selected as the language

5) Publish the containing folder in all languages to the web db, exactly the same as before. Notice now that the "test workflow item" has been published, but with no versions at all. This is what happened with our publish, except from the very root content node which meant countless items got published that should not have been published

Publish again using the exact same code

Now, why our root content node has a version in Japanese is a complete mystery, but at least we have figured out why our draft items got published so we can prevent it in the future. I suspect it has something to do with upgrading Sitecore as there are 2 versions in Japanese which roughly correspond to upgrade dates over the last 2 years.

Cockshy answered 11/9, 2012 at 14:24 Comment(2)
Nicely documented answer. This is actually expected behavior, and a reason why it's important to check item.Versions.Count > 0 in your code before rendering content. A null check is not sufficient.Avigdor
Thanks for this. Ran into exact same issue. Default "content" node had Japanese, German, and Danish versions... what the heck? No other languages defined in System/Languages aside from English. Completely and utterly disagree that I should have to explicitly check if item.Versions.Count > 0 every time I render something. Ridiculous! ESPECIALLY when those version do NOT show up in Content Editor!Suppose
A
15

Likely the issue is that your web service is not running within a site context that has workflow enabled.

The easiest way to do this within your code is to use a SiteContextSwitcher to change to the "shell" site.

using (new SiteContextSwitcher(SiteContextFactory.GetSiteContext("shell")))
{
    //do your publish
}

As for the published items without versions: In theory, that would still happen even with regular publishing. Workflow limits the publishing of item versions, not the items themselves. In your code, when iterating items and in other cases, you need to check whether item.Versions.Count > 0 before rendering.

Avigdor answered 5/9, 2012 at 15:51 Comment(5)
+1. I had the same issue and the problem was that my code was running under the "scheduler" site context which does not have workflow. Even worse, the Item.Publishing.IsPublishable() method will return true if/when an item's workflow is unavailable. Found this out the hard way... not one of my better days.Trash
Thanks very much - this seems entirely plausible as it's a WCF service. I'm going to give it a go shortly to see if it works and I'll get back to you. The strange thing I noticed, also, is that the draft items that were published, when viewed on the live database, were showing absolutely nothing in the Sitecore Desktop in terms of fields or meta data. They were also showing a warning that "The current item does not have a version in "English : English".Cockshy
In theory, that would still happen even with regular publishing. Workflow limits the publishing of item versions, not the items themselves. In your code, when iterating items and in other cases, you need to check whether item.Versions.Count > 0 before rendering.Avigdor
Great answer. Pretty sure I saw something like this going in on the WeBlog code, which I know you contributed to.Defer
OK, sorry it has taken so long, but this has not proved to be the answer unfortunately. I have tested code with and without the above code and the result is the same. Workflow IS adhered to by the publisher, even without the above code. I have done some more digging and found out what the heck is going on.. I will create another answer. It's to do with languages!Cockshy
C
4

TL;DR Root content node had version in another language, removing that version, or only publishing in English language prevented publishing of items in draft mode

OK, so after trying @techphoria414's suggested code, it became clear that the context wasn't the issue. The publisher WAS adhering to workflow after all, but the problem has turned out to be the root content node having a version in another language (Japanese - don't ask me how this got there), but the descendant nodes having no versions in Japanese at all. In fact, our master database is only configured to have English as a language so it shouldn't even be possible for a user other than admin to add a version in another language.

I have conducted some tests and found that the publisher ignores workflow for items that exist in another language. Consider the following scenario:

1) You add a folder and any item underneath ("test workflow item") which has workflow. Don't commit the item, leaving it at version 1, in draft mode (i.e. shouldn't be publishable). The containing folder only has one version in one language (English):

You add a folder and any item underneath which has workflow Folder has english version only

2) You publish the folder with a deep publish to your web db (using the code in my question). This results in the following (folder added, but draft "test workflow item" not added). This is expected behaviour - yay!

You publish the folder with a deep publish

3) Add a new version to the containing folder in a different language.

Add a new version to the containing folder in a different language

4) Check the workflow state of the child item now that Japanese is selected as the language. Notice, in the gutter it no longer says it is in draft mode, but there is no version at all in Japanese (as seen to the right).

Check the workflow state of the child item now that Japanese is selected as the language

5) Publish the containing folder in all languages to the web db, exactly the same as before. Notice now that the "test workflow item" has been published, but with no versions at all. This is what happened with our publish, except from the very root content node which meant countless items got published that should not have been published

Publish again using the exact same code

Now, why our root content node has a version in Japanese is a complete mystery, but at least we have figured out why our draft items got published so we can prevent it in the future. I suspect it has something to do with upgrading Sitecore as there are 2 versions in Japanese which roughly correspond to upgrade dates over the last 2 years.

Cockshy answered 11/9, 2012 at 14:24 Comment(2)
Nicely documented answer. This is actually expected behavior, and a reason why it's important to check item.Versions.Count > 0 in your code before rendering content. A null check is not sufficient.Avigdor
Thanks for this. Ran into exact same issue. Default "content" node had Japanese, German, and Danish versions... what the heck? No other languages defined in System/Languages aside from English. Completely and utterly disagree that I should have to explicitly check if item.Versions.Count > 0 every time I render something. Ridiculous! ESPECIALLY when those version do NOT show up in Content Editor!Suppose

© 2022 - 2024 — McMap. All rights reserved.