Mark Gibbons
Published on

Experience Forms — Getting the Context Site and Item in Submit Actions

Authors

At time of writing, there is no out of the box way to resolve the correct Sitecore.Context.Item or Sitecore.Context.Site from within a Submit Action.

This is a problem if we want to do something with a form on a particular site, page, or language.

Sitecore.Context.Site will resolve to the wrong site in a multi-site instance — it will just take whatever the default catch-all is (usually “website”).

Sitecore.Context.Item just returns null.

I drew inspiration from this question on SSE about how to resolve the correct language.

SiteAwareInitializeAjaxOptions.cs
public class ContextAwareInitializeAjaxOptions : InitializeAjaxOptions
{
    public const string ItemKey = "sc_ctx_item";
    private const string siteKey = "sc_site";

    public ContextAwareInitializeAjaxOptions(IFormRenderingContext formRenderingContext)
        : base(formRenderingContext)
    {
    }

    public override void Process(RenderFormEventArgs args)
    {
        if (!args.IsPost && !args.QueryString.ContainsKey(siteKey))
        {
            args.QueryString.Add(siteKey, Sitecore.Context.Site.Name);
        }
        if (!args.IsPost && !args.QueryString.ContainsKey(ItemKey))
        {
            var item = Sitecore.Context.Item;
            if (item != null)
            {
                args.QueryString.Add(ItemKey, item.ID.ToString());
            }
        }

        base.Process(args);
    }
}
    
    Patch in:
    
<forms.renderForm>
    <processor patch:instead="*[@type='Sitecore.ExperienceForms.Mvc.Pipelines.RenderForm.InitializeAjaxOptions, Sitecore.ExperienceForms.Mvc']"
               type="Your.Solution.Pipelines.RenderForm.ContextAwareInitializeAjaxOptions, Your.Solution" resolve="true"/>
  </forms.renderForm>

Source: gist

You can then access the correct Sitecore.Context.Site as normal, and you can retrieve the current context item in your Submit Action code.

var contextItemIdStr = HttpContext.Current.Request.Params[SiteAwareInitializeAjaxOptions.ItemKey];
if (!string.IsNullOrEmpty(contextItemIdStr))
{
  pageItem = Sitecore.Context.Site.Database.GetItem(contextItemIdStr);
}

Happy travels!