5

The current site I am working with has a custom site provider that does not resolve the context site correctly when trying to open a page in experience editor mode. The parameter sc_site is set to website (default preview site). It seems to be an amalgam of the following: http://sitecoreskills.blogspot.com/2014/10/experimenting-with-sitecore-site.html https://community.sitecore.net/technical_blogs/b/integration_solution_team_blog/posts/sitecore-dynamic-site-provider

There is a utility method in the project that I can use to get the correct site based on where the item is in the tree. I was hoping to override what gets the preview site however this seems to be in the LinkProvider in a non-virtual method (public SiteContext GetPreviewSiteContext(Item item)). It also seems possible to override the method public virtual SiteInfo GetTargetSite(Item item) in LinkBuilder however I'm not sure how I would change the type being used by the LinkProvider where as changing the link provider is a config change I'm familiar with. Registering a custom LinkManager may also fix my issue. I'm not sure if it's possible to override a base service like this through dependency injection.

Is there a different place that I should be looking to override this functionality? I want to override it as low level as possible so it fixes anything else that might be affected by this issue (i.e. clicking the preview mode button has the same issue).

1 Answer 1

4

We've had to solve exactly this problem for experience editor and preview in our 6 Site Sitecore instance. I solved this be adding in two custom commands like so:

Experience Editor Command:

using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using global::Sitecore;
using global::Sitecore.Configuration;
using global::Sitecore.Data;
using global::Sitecore.Data.Items;
using global::Sitecore.Diagnostics;
using global::Sitecore.ExperienceEditor.Utils;
using global::Sitecore.Globalization;
using global::Sitecore.Links;
using global::Sitecore.Pipelines.HasPresentation;
using global::Sitecore.Publishing;
using global::Sitecore.Shell.Framework.Commands;
using global::Sitecore.Sites;
using global::Sitecore.Text;
using global::Sitecore.Web.UI.Sheer;

public class OpenExperienceEditorMultisite : Command
{
    public override void Execute(CommandContext context)
    {
        Assert.ArgumentNotNull(context, "context");
        NameValueCollection parameters = new NameValueCollection();
        bool flag = false;
        if (context.Items.Length == 1)
        {
            Item obj = context.Items[0];
            parameters["uri"] = obj.Uri.ToString();
            parameters.Add("sc_lang", obj.Language.ToString());
            parameters.Add("sc_version", obj.Version.Number.ToString(CultureInfo.InvariantCulture));
            if (HasPresentationPipeline.Run(obj))
                parameters.Add("sc_itemid", obj.ID.ToString());
            else
                flag = true;
        }
        ClientPipelineArgs args = new ClientPipelineArgs(parameters);
        if (!flag)
        {
            args.Result = "yes";
            args.Parameters.Add("needconfirmation", "false");
        }
        Context.ClientPage.Start(this, "Run", args);
    }

    public override CommandState QueryState(CommandContext context)
    {
        Assert.ArgumentNotNull(context, "context");
        if ((UIUtil.IsIE() && UIUtil.GetBrowserMajorVersion() < 7) || !Settings.WebEdit.Enabled)
            return CommandState.Hidden;
        return base.QueryState(context);
    }

    protected void Run(ClientPipelineArgs args)
    {
        Assert.ArgumentNotNull(args, "args");
        if (!SheerResponse.CheckModified())
            return;
        if (args.Parameters["needconfirmation"] == "false" || args.IsPostBack)
        {
            if (args.Result == "no")
                return;
            UrlString urlString = new UrlString("/");
            urlString.Add("sc_mode", "edit");
            if (!string.IsNullOrEmpty(args.Parameters["sc_itemid"]))
                urlString.Add("sc_itemid", args.Parameters["sc_itemid"]);
            if (!string.IsNullOrEmpty(args.Parameters["sc_version"]))
                urlString.Add("sc_version", args.Parameters["sc_version"]);
            SiteContext siteContext = null;
            if (!string.IsNullOrEmpty(args.Parameters["uri"]))
            {
                Item obj = Database.GetItem(ItemUri.Parse(args.Parameters["uri"]));
                if (obj == null)
                {
                    SheerResponse.Alert("Item not found.");
                    return;
                }
                siteContext = LinkManager.GetPreviewSiteContext(obj);
            }
            SiteContext site = siteContext ?? Factory.GetSite(Settings.Preview.DefaultSite);
            if (site == null)
            {
                SheerResponse.Alert(Translate.Text("Site \"{0}\" not found", (object) Settings.Preview.DefaultSite));
            }
            else
            {
                string siteName = string.Empty;
                if (!string.IsNullOrEmpty(args.Parameters["uri"]))
                {
                    Item obj = Database.GetItem(ItemUri.Parse(args.Parameters["uri"]));

                    //this needs to be replaced with your SiteHelper that resolves the sitename based on the current item 
                    siteName = SiteResolverHelper.GetTargetSite(obj).Name;
                }

                string str = args.Parameters["sc_lang"];
                if (string.IsNullOrEmpty(str))
                    str = WebEditUtility.ResolveContentLanguage(site).ToString();
                if (!string.IsNullOrEmpty(args.Parameters["sc_lang"]))
                    urlString.Add("sc_lang", str);
                if (siteName != null) urlString["sc_site"] = siteName;
                PreviewManager.RestoreUser();
                Context.ClientPage.ClientResponse.Eval("window.open('" + urlString + "', '_blank')");
            }
        }
        else
        {
            SheerResponse.Confirm(
                "The current item does not have a layout for the current device.\n\nDo you want to open the start Web page instead?");
            args.WaitForPostBack();
        }
    }
}

Preview Command:

    using System;
    using System.Collections.Specialized;
    using System.Diagnostics.CodeAnalysis;
    using global::Sitecore;
    using global::Sitecore.Configuration;
    using global::Sitecore.Data;
    using global::Sitecore.Data.Items;
    using global::Sitecore.Diagnostics;
    using global::Sitecore.Globalization;
    using global::Sitecore.Links;
    using global::Sitecore.Pipelines.HasPresentation;
    using global::Sitecore.Publishing;
    using global::Sitecore.Shell.DeviceSimulation;
    using global::Sitecore.Shell.Framework.Commands;
    using global::Sitecore.Sites;
    using global::Sitecore.Text;
    using global::Sitecore.Web;
    using global::Sitecore.Web.UI.Sheer; 


    public class PreviewItemMultisite : Command
    {
        public PreviewItemMultisite() 
        {
        }

        public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            if (context.Items.Length != 1)
                return;
            Item obj = context.Items[0];
            NameValueCollection parameters = new NameValueCollection();
            parameters["uri"] = obj.Uri.ToString();
            Context.ClientPage.Start(this, "Run", parameters);
        }

        public override CommandState QueryState(CommandContext context)
        {
            Error.AssertObject(context, "context");
            if (!Settings.Preview.Enabled)
                return CommandState.Hidden;
            if (context.Items.Length != 1)
                return CommandState.Disabled;
            return base.QueryState(context);
        }

        protected void Run(ClientPipelineArgs args)
        {
            Item obj1 = Database.GetItem(ItemUri.Parse(args.Parameters["uri"]));
            if (obj1 == null)
            {
                SheerResponse.Alert("Item not found.");
            }
            else
            {
                string str = obj1.ID.ToString();
                if (args.IsPostBack)
                {
                    if (args.Result != "yes")
                        return;
                    Item obj2 = Context.ContentDatabase.GetItem(LinkManager.GetPreviewSiteContext(obj1).StartPath);
                    if (obj2 == null)
                    {
                        SheerResponse.Alert("Start item not found.");
                        return;
                    }
                    str = obj2.ID.ToString();
                }
                else if (!HasPresentationPipeline.Run(obj1))
                {
                    SheerResponse.Confirm(
                        "The current item cannot be previewed because it has no layout for the current device.\n\nDo you want to preview the start Web page instead?");
                    args.WaitForPostBack();
                    return;
                }
                SheerResponse.CheckModified(false);
                SiteContext previewSiteContext = LinkManager.GetPreviewSiteContext(obj1);
                if (previewSiteContext == null)
                {
                    SheerResponse.Alert(Translate.Text("Site \"{0}\" not found", (object) Settings.Preview.DefaultSite));
                }
                else
                {
                    //this needs to be replaced with your SiteHelper that resolves the sitename based on the current item 
                    string siteName = SiteResolverHelper.GetTargetSite(obj1).Name;

                    WebUtil.SetCookieValue(previewSiteContext.GetCookieKey("sc_date"), string.Empty);
                    PreviewManager.StoreShellUser(Settings.Preview.AsAnonymous);
                    UrlString urlString = new UrlString("/");
                    urlString["sc_itemid"] = str;
                    urlString["sc_mode"] = "preview";
                    urlString["sc_lang"] = obj1.Language.ToString();
                    if (siteName != null) urlString["sc_site"] = siteName;
                    DeviceSimulationUtil.DeactivateSimulators();
                    if (UIUtil.IsChrome())
                        SheerResponse.Eval("setTimeout(function () { window.open('" + urlString + "', '_blank');}, 0);");
                    else
                        SheerResponse.Eval("window.open('" + urlString + "', '_blank');");
                }
            }
        }
    }

Then the following config patches are needed:

<sitecore>
    <commands>
        <command name="webedit:openexperienceeditor">
            <patch:attribute name="type" value="YourSite.Sitecore.Extensions.OpenExperienceEditorMultisite, YourSite.Sitecore.Extensions" />
        </command>
        <command name="item:preview">
            <patch:attribute name="type" value="YourSite.Sitecore.Extensions.PreviewItemMultisite, YourSite.Sitecore.Extensions" />
        </command>
    </commands>
</sitecore>

This should then set your sc_site parameter correct to the right site.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.