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.