If like me, you like to use standard .NET MVC methods, you'll soon find that doing async calls to ActionResults leaves you without an UmbracoContext.

Of course this makes total sense. As at this point in the application we are out of 'Umbraco' and it has no idea of where we are in the Website (What page we are on).

I have a little (Hacky) helper class to help deal with this, you can view the class below. And to use it, I would have something like this, where in the first lines of the ActionResult I would call the ContextHelper.

 [HttpPost]
 public ActionResult SomethingCool()
 {
        if (Request.IsAjaxRequest())
        {
            // Sort the UmbracoContext
            ContextHelper.EnsureUmbracoContext();

            // Do rest of my code
        }
        ....
 }

ContextHelper Class

public static class ContextHelper
{
    /// <summary>
    /// To get at the IPublishedCaches it is only available on the UmbracoContext (which we need to fix)
    /// but on methods that operate async, there isn't one, so we need to make our own to get at the cache
    /// object by creating a fake HttpContext. Not pretty but it works for now.
    /// </summary>
    /// <returns></returns>
    public static UmbracoContext EnsureUmbracoContext()
    {
        if (UmbracoContext.Current == null)
        {
            var dummyHttpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("blah.aspx", "", new StringWriter())));
            return UmbracoContext.EnsureContext(
                dummyHttpContext,
                ApplicationContext.Current,
                new WebSecurity(dummyHttpContext, ApplicationContext.Current),
                UmbracoConfig.For.UmbracoSettings(),
                UrlProviderResolver.Current.Providers,
                false);
        }

        return UmbracoContext.Current;
    }

    /// <summary>
    /// Ensures we always have PublishedContent available
    /// </summary>
    /// <param name="nodeId"></param>
    public static void EnsurePublishedContent(int nodeId)
    {
        UmbracoContext currentContext;
        if (UmbracoContext.Current == null)
        {
            currentContext = EnsureUmbracoContext();
        }
        else
        {
            currentContext = UmbracoContext.Current;
        }

        var contentNode = new UmbracoHelper(currentContext).TypedContent(nodeId);

        SetPublishedContent(currentContext, contentNode);
    }

    /// <summary>
    /// Ensures we always have PublishedContent available
    /// </summary>
    /// <param name="contentNode"></param>
    public static void EnsurePublishedContent(IPublishedContent contentNode)
    {
        UmbracoContext currentContext;
        if (UmbracoContext.Current == null)
        {
            currentContext = EnsureUmbracoContext();
        }
        else
        {
            currentContext = UmbracoContext.Current;
        }

        SetPublishedContent(currentContext, contentNode);
    }

    /// <summary>
    /// Resets the Published Content if missing
    /// </summary>
    /// <param name="currentContext"></param>
    /// <param name="contentNode"></param>
    private static void SetPublishedContent(UmbracoContext currentContext, IPublishedContent contentNode)
    {
        if (currentContext.PublishedContentRequest == null)
        {
            var requestUrl = new Uri("http://localhost");
            var request = HttpContext.Current.Request;
            if (request != null)
            {
                requestUrl = request.Url;
            }
            var uri = UriUtility.UriToUmbraco(requestUrl);
            UmbracoContext.Current.PublishedContentRequest = new PublishedContentRequest(uri, currentContext.RoutingContext, UmbracoConfig.For.UmbracoSettings().WebRouting, s => Roles.Provider.GetRolesForUser(s))
            {
                PublishedContent = contentNode
            };
        }
    }
}