I am working on a project where I want to keep users logged in using access tokens/refresh tokens. I store these values in a cookie and whenever a user visits the site, I want to automatically log him in regardless of the page that he uses to access the site. To do this, I created a BaseController, that all other controllers inherit from. The BaseController looks like this:
public abstract class BaseController : Controller
{
    public BaseController()
    {
        LoginModel.SetUserFromAuthenticationCookie();
    }
}
This constructor gets executed every time before an action is executed and is therefore exactly what I want. The problem is that SetUserFromAuthenticationCookie() is an async method, because it has to do calls to other async methods. It looks like this:
public async static Task SetUserFromAuthenticationCookie()
    {
        // Check if the authentication cookie is set and the User is null
        if (AuthenticationRepository != null && User == null)
        {
            Api api = new Api();
            // If a new authentication cookie was successfully created
            if (await AuthenticationRepository.CreateNewAuthenticationCookieAsync())
            {
                var response = await api.Request(HttpMethod.Get, "api/user/mycredentials");
                if(response.IsSuccessStatusCode)
                {
                    User = api.serializer.Deserialize<UserViewModel>(await response.Content.ReadAsStringAsync());
                }
            }
        }
    }
The problem is that the execution order is not as I anticipated and because of that the user does not get logged in. I tried to work with .Result for the async methods, but that resulted in a deadlock. Besides that I read many threads on SO concerning the issue and eventually also found one that managed to get the login to work: How would I run an async Task<T> method synchronously?. It is somewhat hacky though and works with this helper:
public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task<T> method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task<T> method to execute</param>
    public static void RunSync(Func<Task> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        synch.Post(async _ =>
        {
            try
            {
                await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
        SynchronizationContext.SetSynchronizationContext(oldContext);
    }
    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        T ret = default(T);
        synch.Post(async _ =>
        {
            try
            {
                ret = await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
        SynchronizationContext.SetSynchronizationContext(oldContext);
        return ret;
    }
    private class ExclusiveSynchronizationContext : SynchronizationContext
    {
        private bool done;
        public Exception InnerException { get; set; }
        readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
        readonly Queue<Tuple<SendOrPostCallback, object>> items =
            new Queue<Tuple<SendOrPostCallback, object>>();
        public override void Send(SendOrPostCallback d, object state)
        {
            throw new NotSupportedException("We cannot send to our same thread");
        }
        public override void Post(SendOrPostCallback d, object state)
        {
            lock (items)
            {
                items.Enqueue(Tuple.Create(d, state));
            }
            workItemsWaiting.Set();
        }
        public void EndMessageLoop()
        {
            Post(_ => done = true, null);
        }
        public void BeginMessageLoop()
        {
            while (!done)
            {
                Tuple<SendOrPostCallback, object> task = null;
                lock (items)
                {
                    if (items.Count > 0)
                    {
                        task = items.Dequeue();
                    }
                }
                if (task != null)
                {
                    task.Item1(task.Item2);
                    if (InnerException != null) // the method threw an exeption
                    {
                        throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                    }
                }
                else
                {
                    workItemsWaiting.WaitOne();
                }
            }
        }
        public override SynchronizationContext CreateCopy()
        {
            return this;
        }
    }
If I then change the content of the BaseController constructor to:
AsyncHelpers.RunSync(() => LoginModel.SetUserFromAuthenticationCookie());
the functionality works as anticipated.
I would like to know though if you have any suggestions on how to do this in a nicer manner. Perhaps I should move the call to the SetUserFromAuthenticationCookie() to another location, but at this time I do not know where that would be.
 
     
     
    