How to publish Sitecore items programatically that have been updated using the editor
Asked Answered
H

3

5

I have been trying to publish items through code that have been changed in the Sitecore editor. If I update field values programatically and publish those changes, it works fine though.

Our content management editors regularly make changes in the editor without necessarily publishing them. We want to provide them with a functionality to click one button that publishes all relevant changes and clears the Sitecore cache.

I don't want to publish the whole site, only several predefined items.

We are currently using Sitecore.NET 6.4.1 (rev. 110720). I am not in the possibility to update Sitecore.

I tried these options:

Option 1: instantiating a new publisher object

Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Database web = Sitecore.Configuration.Factory.GetDatabase("web");

Sitecore.Publishing.PublishOptions publishOptions = new Sitecore.Publishing.PublishOptions(master,
                        web,
                        Sitecore.Publishing.PublishMode.SingleItem,
                        item.Language,
                        System.DateTime.Now); 

Sitecore.Publishing.Publisher publisher = new Sitecore.Publishing.Publisher(publishOptions);

publisher.Options.RootItem = item;

publisher.Options.Deep = true;

publisher.Publish(); 

Option 2: using the static publishmanager

Database db = Sitecore.Configuration.Factory.GetDatabase("web");
Database[] databases = new Database[1] { db };

Sitecore.Handle publishHandle = Sitecore.Publishing.PublishManager.PublishItem(item, databases, db.Languages, true, false);

Both methods are wrapped in a using statement to use the same account which is used by the content management editors.

string domainUser = @"sitecore\admin";

if (Sitecore.Security.Accounts.User.Exists(domainUser))
{
      Sitecore.Security.Accounts.User user =
      Sitecore.Security.Accounts.User.FromName(domainUser, false);

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

}

The logs don't show anything noteworthy as far as I can tell

ManagedPoolThread #7 13:41:46 INFO  Job started: Publish to 'web'
ManagedPoolThread #7 13:41:46 INFO  HtmlCacheClearer clearing HTML caches for all sites (5).
ManagedPoolThread #7 13:41:46 INFO  HtmlCacheClearer done.
ManagedPoolThread #7 13:41:46 INFO  Job ended: Publish to 'web' (units processed: 2)
ManagedPoolThread #5 13:41:46 INFO  Job ended: Publish (units processed: )

It is definetely not a caching issue, because when publishing manually in the editor before clearing the cache programatically, the changes are visible in code.

So I'm looking for a way to programatically publish a predefined list of updated items, disregarding the way the edit has been made.

Hymnist answered 25/5, 2016 at 9:8 Comment(4)
In your option2 (publishmanager), you are publishing to the master database. Could you try that one with the web database as target? Also, make sure you are using the right database context (maybe use a db switcher to master db as well).Vaticinate
doesn't seem to work either. I added a DatabaseSwitcher and changed the database to web, also tried the other way around.Hymnist
I use option 2, can you update the code in the question with the web?, other The publish target is not always "web", better not use this hardcoded, 2) If the parent not exists in the web database the item will not be publishedHunkydory
Updated to "web", that wasn't the issue because I tried both to be sure, but I think I figured it out, will post an answer laterHymnist
C
5

This is how I used to publish items in a Sitecore 6.5 solution. Looks very similar to your first solution, and this still works fine for me. Do you see any errors / info logs in the Sitecore log?

public void PublishItem(Database dbMaster, Database dbWeb, Item iParent)
{
    try
    {
        PublishOptions po = new PublishOptions(dbMaster, dbWeb, PublishMode.SingleItem, Sitecore.Context.Language, DateTime.Now);
        po.RootItem = iParent;
        po.Deep = true; // Publishing subitems

        (new Publisher(po)).Publish();
    }
    catch (Exception ex)
    {
        Sitecore.Diagnostics.Log.Error("Exception publishing items from custom pipeline! : " + ex, this);
    }
}

Regarding the caching, that should be handled by the publishing operation automatically on the web database.

Sometimes when I manipulate items programatically on the master database, I force Sitecore to clear the cache only for those items with the code below:

Item baseitem = Database.GetDatabase("master").SelectSingleItem(sitecore_path);
if (baseitem != null)
{
    //Sitecore.Caching.CacheManager.ClearAllCaches();  
    string load = String.Concat(new object[] { "item:load(id=", baseitem.ID, ",language=", baseitem.Language, ",version=", baseitem.Version, ")" });
    Sitecore.Context.ClientPage.SendMessage(this, load);
    String refresh = String.Format("item:refreshchildren(id={0})", baseitem.Parent.ID);
    Sitecore.Context.ClientPage.ClientResponse.Timer(refresh, 2);
}
Cornall answered 25/5, 2016 at 11:23 Comment(7)
I tried using your code, but it is basically the same is my 1ste option so no differece in result.Hymnist
Do you see anything in the log?Cornall
From the logs, looks like everything went fine, 2 items were pushed and the caches were cleared. What is the problem then? Is your website pointing to the web database, or where do you check these changes?Cornall
I'm checking in the dbbrowser so I can easily switch between master/web db. I'm also checking a custom webservice that is used to get the data from Sitecore.Hymnist
Try clearing the cache using /sitecore/admin/cache.aspx to make sure it's not some caching behind this. It looks the publishing went fine.Cornall
Tried it. I don't think it is a caching issue. I'm changing values in the dbbrowser in master, (try to) do a publish in code, and I would expect the value to change in web. This works fine when I publish in the editor, but not through publishing in code.Hymnist
When publishing in the editor I don't even need a cache refresh to see the changed value in the dbbrowser.Hymnist
H
2

After all, the issue was not really in the code but just the wrong order of doing things and using correct databases.

  1. Update the field in the Sitecore editor
  2. Clear the master database cache
  3. Get the item explicitly from the master database
  4. Publish the item with the "web" database as target
  5. Clear the "web" database cache

Final code to publish an item:

using (new Sitecore.SecurityModel.SecurityDisabler())
{
    string itemId = "E7A2DE22-4338-49A6-840F-4B3124F1FFBD";

    Database webdb = Sitecore.Configuration.Factory.GetDatabase("web");
    Database masterdb = Sitecore.Configuration.Factory.GetDatabase("master");

    ClearSitecoreDatabaseCache(masterdb);

    Item masterItem = masterdb.GetItem(new ID(itemId));

    // target databases
    Database[] databases = new Database[1] { webdb };

    Sitecore.Handle publishHandle = Sitecore.Publishing.PublishManager.PublishItem(masterItem, databases, webdb.Languages, true, false);

    ClearSitecoreDatabaseCache(webdb);
}

Code to clear the cache:

public void ClearSitecoreDatabaseCache(Database db)
{
    // clear html cache
    Sitecore.Context.Site.Caches.HtmlCache.Clear();

    db.Caches.ItemCache.Clear();
    db.Caches.DataCache.Clear();

    //Clear prefetch cache
    foreach (var cache in Sitecore.Caching.CacheManager.GetAllCaches())
    {
        if (cache.Name.Contains(string.Format("Prefetch data({0})", db.Name)))
        {
            cache.Clear();
        }
    }
}
Hymnist answered 25/5, 2016 at 13:0 Comment(1)
I tried your code and it works perfectly. Personally, i don't use your clearcache function cause i already have the item object to publish in my code. No need to search it in the master database.Shardashare
I
2

According to me, clearing all caches while publishing is not a practical way. It will impact on site performance a lot.

Actually, after editing the content from dbbrowser, you just need to clear item specific cache (for edited items only). To know how to do that, check - http://sitecoreblog.patelyogesh.in/2013/08/sitecore-partial-cache-clear-programmatically.html.

Means, steps you should take: 1. Edit content from DBBrowser 2. Before publishing, clear item specific cache for publishing items 3. No additional "web" or "master" cache clearing required publishing.

I'm sure this will help your solution.

Ironmonger answered 25/5, 2016 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.