Home > Code > RunAs method for running code in specific user SPServiceContext

RunAs method for running code in specific user SPServiceContext

You may have the need to run some code in a SPServiceContext of a specific user. e.g. when dealing with user profiles or activities.

This can be achieved by using a combination of the SPUser, WindowsIdentity, GenericPrincipal and the GetContext method of SPServiceContext.

From these we can set the HttpContext.Current.User property to the specified user.

Don’t forget to set the context back after the code has executed!

Below is a helper method that makes this very easy.

I haven’t done any solid testing on performance etc. so the usual caveats apply.


// Example calling code

RunAs("http://asharepointsite", "THEDOMAIN\THEUSER", c =>
{
    // The code to execute. e.g. get a the UserProfileManager as the passed in user
    var upm = new UserProfileManager(c, true);

    // Do some stuff to the UPM as the passed in user
});

// Helper method

private static void RunAs(string siteUrl, string userName, Action<SPServiceContext> contextToUse)
{
    try
    {
        var currentSetting = false;
        var currentHttpContext = HttpContext.Current;
        SPUser currentUser = null;

        if (SPContext.Current != null)
        {
            if (SPContext.Current.Web != null)
            {
                currentUser = SPContext.Current.Web.CurrentUser;
            }
        }

        SPSecurity.RunWithElevatedPrivileges(delegate
        {
            using (var site = new SPSite(siteUrl))
            {
                using (var web = site.OpenWeb())
                {
                    try
                    {
                        var user = web.EnsureUser(userName);

                        currentSetting = web.AllowUnsafeUpdates;
                        web.AllowUnsafeUpdates = true;

                        var request = new HttpRequest("", web.Url, "");

                        HttpContext.Current = new HttpContext(request,
                                                                new HttpResponse(
                                                                    new StringWriter(CultureInfo.CurrentCulture)));

                        HttpContext.Current.Items["HttpHandlerSPWeb"] = web;

                        var wi = WindowsIdentity.GetCurrent();

                        var newfield = typeof (WindowsIdentity).GetField("m_name",
                                                                            BindingFlags.NonPublic |
                                                                            BindingFlags.Instance);

                        if (newfield != null) newfield.SetValue(wi, user.LoginName);

                        if (wi != null) HttpContext.Current.User = new GenericPrincipal(wi, new string[0]);

                        var elevatedContext = SPServiceContext.GetContext(HttpContext.Current);

                        contextToUse(elevatedContext);

                        //Set the HTTPContext back to "normal"
                        HttpContext.Current = currentHttpContext;

                        if (currentUser != null)
                        {
                            var winId = WindowsIdentity.GetCurrent();

                            var oldField = typeof (WindowsIdentity).GetField("m_name",
                                                                                BindingFlags.NonPublic |
                                                                                BindingFlags.Instance);

                            if (oldField != null) oldField.SetValue(winId, currentUser.LoginName);

                            if (winId != null)
                                HttpContext.Current.User = new GenericPrincipal(winId, new string[0]);
                        }
                    }
                    catch (Exception ex)
                    {
                        // Log or whatever
                    }
                    finally
                    {
                        web.AllowUnsafeUpdates = currentSetting;
                    }
                }
            }
        });

    }
    catch (Exception exO)
    {
        // Log or whatever
    }
}

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: