Sitecore workflow - publishing item in draft state - sitecore

I am currently working with sitecore items that are in a draft workflow state. The following happens:
Create an item that will go into workflow draft state
Publish the item/publish the parent item (with sub items selected) to the web db from master db, ignore publish warning prompt
The item will appear in the web database but with no versions
This causes our controls to render the item but with standard values because there are no versions. Of course we could add a check for item.Versions.Count > 0 but my question is why this is happening?
Surely an item in draft workflow state should never appear in the web database in any way?
The workflow being used is pretty standard and has no customisation. The states and commands are:
Draft
Submit
Awaiting approval
Reject
Approve
Validation action
Approved
Auto publish
Thanks in advance.

I believe you can use the following property on each of your site nodes in the config.
<site name="website" filterItems="true" ... />
If setting this to true doesn't resolve the issue then you can add the following pipeline step, in addition to the above setting, before the Sitecore.Pipelines.FilterItem.EnsureFilteredItem step.
public class HideEmptyItem
{
public void Process(FilterItemPipelineArgs args)
{
if ((Context.Site != null && Context.Site.DisplayMode == DisplayMode.Normal) && args.Item.Paths.Path.StartsWith("/sitecore/content/"))
{
try
{
Context.Site.DisableFiltering = true;
if (args.Item.Database.GetItem(args.Item.ID, Context.Language).Versions.Count == 0)
{
args.FilteredItem = null;
}
}
finally
{
Context.Site.DisableFiltering = false;
}
}
}
}
Also ensure the following is set accordingly, the default is false;
<setting name="Publishing.PublishEmptyItems" value="false" />
I actually encountered this issue but in a different way. If you use publishing restrictions you can end up with an item that has no versions on it but can still be published. There are many ways for an item to end up with no versions, not just a new item with a single version that hasn't been pushed through a workflow. The above fix was actually provided by Sitecore support and worked for me.
If this doesn't work for you then I would suggest adding in check when items are published to see if they have any versions, although I believe that's what the fix above is supposed to do.
EDIT: Changed property from "hideEmptyItems" to "filterItems" and added further explanation.

My personal opinion is that you should be checking for version count. If you plan on ever supporting a multilingual site, it is entirely possible to have a version in one language, but not another (not approved yet in Spanish, for example). You would want your controls to handle that scenario (or execute fallback).
It is entirely valid that the current user in the current language may have no valid versions come back for them. I would expect that the business logic of the web controls should handle those scenarios.

To explicitly answer your question, this happens because the item is not null but it has no versions. A version is a dimension of an item and it happens to be "empty" if you have no version. So your code gets a valid non null item, but has no field values since there is no version and thus your controls don't fill with data.
This will only happen for new items. Example: create an item and you have v1 which is is in draft. You "publish" the item. The item goes out to the web DB but the v1 dimension of it does not, so you're left with a non null item with no versions.
As Jay said, the solution is to check for this when you query items.

First, the default workflow should set to the item's template "__Standard Values".
Second, workflow with "admin" account doesn't work. Try another account.

Related

How to install feature based on the property set in custom action?

I am trying to install one from two features based on the value that should be set inside of the custom action.
Firstly, I set the value of a property:
UINT __stdcall ConfigurationCheckAction(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_INSTALL_FAILURE;
hr = WcaInitialize(hInstall, "ConfigurationCheckAction");
if (condition) {
MsiSetProperty( hInstall, TEXT("STREAM"), TEXT("RED") );
}
else {
MsiSetProperty( hInstall, TEXT("STREAM"), TEXT("BLUE") );
}
return WcaFinalize(er);
}
Secondly, I make two conditions per two features:
<Feature Id='Complete' Level='1'>
<Feature Id="Red" ConfigurableDirectory="TARGETDIR" Title="F1" Level="0">
<Condition Level="1">STREAM</Condition>
</Feature>
<Feature Id="Blue" ConfigurableDirectory="TARGETDIR" Title="F2" Level="0">
<Condition Level="1">NOT STREAM</Condition>
</Feature>
</Feature>
Note that I don't define property inside of the wxs file previously, as I would like to set it from the custom action.
My custom action is called before InstallInitialize and Execute is immediate.
From the installation log I have confirmation that the property is set.
However, my conditional installation does not work, as it seems like what is in the condition is always evaluated as false.
I tried evaluating conditions:
STREAM, STREAM=RED, STREAM="RED", < ![CDATA[STREAM=RED]]>
I am running out of ideas what to do and would appreciate help.
Too late to test all of this, but here goes with some information. I will check back tomorrow. Essentially I think the problem is your custom action sequencing. Try before Costing.
Some things to consider:
Custom action sequencing: you need to sequence your custom action right and it needs to be present in both silent and interactive installation modes.
Did you try to sequence the set property custom action before CostInitialize? You state you set it before InstallInitialize, but try it before CostInitialize instead (you might have tried).
And did you remember to insert this custom action in the InstallUISequence as well as the InstallExecuteSequence? You need to insert in both sequences in case the setup runs in silent mode. Before CostInitialize in both sequences I believe.
Feature Level: manipulating features via the feature level and INSTALLLEVEL is just one way to do feature control, you can also set features via the command line or using a custom action.
Setting a feature level to 0 should hide the feature from view in the setup's custom dialog.
Setting a feature level higher than the setup's INSTALLLEVEL will deselect the feature from installation.
And the other way around setting a feature level lower or equal to the setup's INSTALLLEVEL will select the feature for installation.
The conditional syntax allowed is quite flexible, and could provide the functionality you need outright - but I have never used them properly. Here is an example from the Installshield forum.
ADDLOCAL & REMOVE: you can manipulate the feature selection by changing the values of the ADDLOCAL and REMOVE properties from a custom action (technically also REINSTALL and ADVERTISE) - and these properties can be set via the command line as well.
Win32: you can also use the Win32 functions MsiGetFeatureState and MsiSetFeatureState - from a C++ custom action - to set feature selection.
Frankly it is a bit mad the whole thing. Also keep in mind that there are feature action states (what is going to happen to a feature) and feature installed states (what state it is in). The Win32 function documentation should explain.
Cross-linking for easy retrieval:
Unselected Feature Being Installed
I have done something similar, but we ended up controlling this at a component level(adding the condition to the <Component/> elements instead of the feature element using a transform during heat). But our condition utilizes CDATA while also using double quotes for the value, which you don't list in what you've tried. So first I'd try the following conditions in your features:
<Condition><![CDATA[STREAM="RED"]]></Condition>
<Condition><![CDATA[STREAM="BLUE"]]></Condition>
If that still does not work, I would try the following:
Add the STREAM property with a default value to your WiX. Then test it with that default value to see if having the default value set to begin with makes it work. That could mean you need to set the property sooner, possibly off a UI event. <Property Id="STREAM" Value="RED"/>
As a last resort, you could add the conditions to each component as I did, but we only did that for very specific reasons, hopefully you can get the conditional feature to work with the above suggestions!
I hope the above fixes your problem, or at least leads you to the answer!
Thank you for your replies. In the end, a combination of your suggestions helped me.
I want to state what did and what did not work:
Adding property to WiX with a default value was not necessary (as well with adding property of this property Secure='yes')
Calling custom action before CostInitialize did not solve the problem on its own, but I believe it was one of the factors that resolved an issue.
Conditional sintax was corrected by:
a) Putting condition inside of CDATA and adding quotes to the value of property as suggested: <Condition><![CDATA[STREAM="RED"]]></Condition>
b) Reversing condition levels so feature has condition level 1 and condition has level 0. This means that feature is always installed, unless the condition expression is false.
Concerning the correct order of the custom actions, the description of the custom action type 51 contains the decisive hint:
"To affect a property used in a condition on a component or feature, the custom action must come before the CostFinalize action in the action sequence."

MURA CMS: how to add a page programmatically

So, what can I say? How do I go about adding a page programmatically in MURA CMS? Preferably version 6.1.
I am building a plugin that needs to create a couple of pages in the Site Manager. I want to add this routine in the 'install' method of the 'plugin/plugin.cfc' component.
I have been unable to find any pointers to this on line, which, perhaps, means this particular issue cannot be resolved. But, I live in hope.
Thanks people, in advance, for any help on this one.
When you add content to Mura, the key is that you'll need to know the parentid of where you wish the new content item(s) to live. Other than that, Mura offers an easy way perform CRUD operations on content items. You can read more about it at http://docs.getmura.com/v6/back-end/base-mura-objects-beans/loading-beans/ (based on the version you've specified). I'd also like to point out that the documentation has been greatly expanded in the latest version which can be found at http://docs.getmura.com/v7/mura-developers/mura-beans-objects/common-bean-objects/content-bean/. While the concepts and syntax still apply to older version, some newer methods for working with Mura content objects have been added since v6.1. I also highly recommend upgrading soon, as v7.1 is about to be released as well (as of Feb. 2018).
That said, the only two required fields/attributes are title and parentid. Here's the basic code for being able to do what you need:
// load the parent content item
parentBean = $.getBean('content').loadBy(title='Home');
// you may want to verify the `parentBean` actually exists before proceeding
if ( parentBean.getIsNew() ) {
Throw(message='parentBean does NOT exist!');
}
// v6.1 syntax
newBean = $.getBean('content')
.setValue('title', 'Some Title')
.setValue('parentid', parentBean.getContentID())
.save();
// v7.0+ syntax
newBean = $.getBean('content')
.set('title', 'Some Title')
.set('parentid', parentBean.get('contentid'))
.save();
// after saving, you can check for errors
if ( !StructIsEmpty(newBean.getErrors()) ) {
WriteDump(var=newBean.getErrors(), abort=true);
}
You could clearly set other attributes (as defined in the earlier links) as well, if desired.
Cheers!

Sitecore updates a lot of items on smart publish

I'm using Sitecore 8.0 Update 5.
Each time I'm doing a "Smart" publish with languages other than English I can see that thousands of items being updated.
Job started: Publish to 'web'
Items created: 0
Items deleted: 0
Items updated: 56207
Items skipped: 13057
Job ended: Publish to 'web' (units processed: 69258)
I've enabled tracing and in the logs I can see that Sitecore updateds shared fields of those items
##Publish Item: Name=sitecore, Uri=sitecore://master/{11111111-1111-1111-1111-111111111111}?lang=zh&ver=1, Operation=Updated, ChildAction=Allow, Explanation=Shared fields were published.
##Publish Item: Name=templates, Uri=sitecore://master/{3C1715FE-6A13-4FCF-845F-DE308BA9741D}?lang=zh&ver=1, Operation=Updated, ChildAction=Allow, Explanation=Shared fields were published.
##Publish Item: Name=List Manager, Uri=sitecore://master/{D2833213-CB77-431A-9108-55E62E4E47FD}?lang=zh&ver=1, Operation=Updated, ChildAction=Allow, Explanation=Shared fields were published.
And the list goes on like that for pretty much every item in the tree.
Armed with dotPeek I was able to find a method in publishing pipeline that is responsible for determining publish action:
private void HandleSourceVersionNotFound(Item sourceItem, PublishItemContext context)
{
Assert.ArgumentNotNull((object) sourceItem, "sourceItem");
Item targetItem = context.PublishHelper.GetTargetItem(sourceItem.ID);
if (targetItem != null)
{
Item[] versions = targetItem.Versions.GetVersions(true);
if (versions.Length > 0 && versions.Any(v => v.Language != sourceItem.Language)) || Settings.Publishing.PublishEmptyItems)
context.Action = PublishAction.PublishSharedFields;
else
context.Action = PublishAction.DeleteTargetItem;
}
else if (Settings.Publishing.PublishEmptyItems)
context.Action = PublishAction.PublishSharedFields;
else
context.AbortPipeline(PublishOperation.Skipped, PublishChildAction.Skip, "No publishable source version exists (and there is no target item).");
}
Here we can see that it checks item versions and if there are versions on language other than English it sets action to PublishAction.PublishSharedFields.
Settings.Publishing.PublishEmptyItems is set to false in my case, so this should not trigger shared fields publish.
I thought that the only "system" items with non-English version in my solution were languages, but when I looked on one of the item from the logs I discovered a really interesting thing:
Sitecore default languages
These appears to be Sitecore "default" languages.
This behavior causes a performance problem with publishing when I enable Language Fallback module. (https://marketplace.sitecore.net/en/modules/language_fallback.aspx)
My questions are:
Is this an expected behavior for Sitecore to push shared fields each time when you publish?
Is this an expected behavior for Sitecore to push shared fields on system items when they have versions only on these default languages?
How can I disable those default languages and remove versions on these languages? (Powershell?)
What are the implications of removing these default languages?
Is there anything that I'm doing wrong that can cause this kind of behavior?
UPD. On a different environment where it goes over 100k items threshold and triggers full index rebuild, which is pretty expensive operation. (With or without language fallback)
Thanks in advance!
How can I disable those default languages and remove versions on these languages?
If the language is registered under /sitecore/system/Languages, Sitecore should remove all item version, for the language, if you remove the language.
If the language is not registered (or Sitecore, for some reason, fails to remove it when you remove it) under /sitecore/system/Languages, do a database cleanup (Control Panel > Database > Clean Up Databases). Sitecore will remove any version of items that are in a language that is not registered.
What are the implications of removing these default languages?
Unless you plan on using those languages in the future, no real implication.
Is this an expected behavior for Sitecore to push shared fields each time when you publish?
=> No but the code you've found isn't used for every item. That action occurs when the Source Version isn't found ea the item exists in web but not in master. That's why it's either publish shared fields (in case other versions do exist) or delete the item completely from web (because it no longer exists in master).
Is this an expected behavior for Sitecore to push shared fields on system items when they have versions only on these default languages?
=> I'm unable to answer this question as is without deeper investigation for which I do not have time at this point I'm sorry.
How can I disable those default languages and remove versions on these languages? (Powershell?)
=> These languages aren't registered, they're showing up because these items do have a version in those languages. So if you remove the versions of all system items in those languages they'll no longer show up. You can create a version in any language even a non-existing one through code.
What are the implications of removing these default languages?
=> Any content editors that are using that language might suddenly see english (or a leftover language) instead of their preferred set Sitecore Editing language. Beyond that it should not matter.
Is there anything that I'm doing wrong that can cause this kind of behavior?
=> Not that I can see from what you've presented thus far.

Sitecore 7.2 Update3 $name Issue

We are facing one issue in Sitecore 7.2 Update 3.
Sitecore.Context.Item is returning old version and that version is not available in web DB, so we are getting $name for all the fields. On page load $name is displaying, if I refresh the page then it works fine after 5 minutes again we are getting $name, let me know if any body face this issue.
This issue has been addressed since Sitecore CMS and DMS 7.2 rev.151021 (7.2 Update-5):
Obsolete item versions might be present in search indexes after publishing. This has been fixed. (440383)
See the release notes on SDN for more information about the changes.
Additionally, check the known issue article with a possible workaround:
https://kb.sitecore.net/articles/992608
We fixed the issue by making sure that sitecore was returning the latest version of the context. We found out that sitecore, for some reason, was looking for a version on the web DB, and this was not the latest version. So we applied this:
Before:
public virtual Item Item
{
get { return Context.Item; }
}
After:
public virtual Item Item
{
get { return Context.Item.Versions.GetLatestVersion(); }
}
Maby something with a language version.
put the language code in the URL to ensure that you do not change the language, or check the Sitecore language cookie.
Other thing to check, In IIS check the Application pool, Advanced Settings, Maximum Worker Processes set it to 1 to ensure there is only 1 worker which should give every time the same response.

Sitecore: Seemingly Random errors appear

we are experiencing some very odd errors in our installation.
Some times out of nowhere Sitecore throws an error:
Assert: Value Cannot be null. Parameter: Item.
The closest i have come to identifying the problem is narrowing it down to either an index or the web database.
Anyway, if I log into sitecore the Item is just missing, i can fix it in 3 ways:
Rebuild the index.
Recycle app pool
iisreset
Does any of you have an idea why this might be happening? We are running Sitecore.NET 6.5.0 (rev. 120706). Any help will be deeply appreciated.
You are describing a system stability issue, so I recommend opening a ticket with Sitecore support (http://support.sitecore.net). This sort of issue is difficult to troubleshoot over Stack Overflow, since we do not have access to your logs and configuration.
When opening the ticket, I recommend using the Support Package Generator which bundles up all the information (Web.config, App_Config files, IIS settings, Sitecore log files) that Sitecore Support needs to troubleshoot the issue. It's a pretty nifty tool.
That said, from what you describe, it sounds like the issue is related to caching. The fact that restarting IIS resolves the issue indicates that the item is in the Web database, but the runtime doesn't see it. You can prove out whether this is the issue by clearing cache using the /sitecore/admin/cache.aspx screen. If your cache is not getting updated properly, you should review your configuration against the guidelines in the SDN Scaling Guide.
Based on knowing you're using the Advanced Database Crawler, your issue may be how you're converting a SkinnyItem to an Item. I've had this issue before. If you look at the SkinnyItem.cs class, there's a GetItem() method to convert it into an Item. You can see it uses the database to get the item by its ID, language, and version number. Its possible that when you publish from master to web, you are publishing a new version # of an existing item and thus the new version exists in the web DB, but the index is not updated and references the old version. So, this GetItem() call would use the previous version # and the item would be null. One way to fix this is instead of calling that GetItem() method, just use your own code to get the latest version of that item from Sitecore, e.g.
Item item = Sitecore.Context.Database.GetItem(someSkinnyItem.ItemID);
Instead of
Item item = someSkinnyItem.GetItem();
Here's an example flow:
Foo item created in master DB as version 1.
Publish Foo to web
Index will pick up version 1 in web DB and put in index.
Any querying code against index will convert the SkinnyItem to an Item via that GetItem() method and will pass 1 as the version #.
Page will load, no error in log
Back in master, create version 2 of Foo and publish.
Index may not get updated right away or even if configured wrong.
Code that looks against index will call GetItem() and still call with version 1 since that's in the index
But when you published, web no longer has version 1, it now has version 2, and thus that specific version of that item Foo is null
Error shows in log
On a similar note, here's a blog post by Alex Shyba (creator of the ADC) on how to sync HTML cache clearing with the index updates. That may help.