0

I'm often using pattern where I create class Workspace. This class has some basic functionality and on of them is opening of webs, and also web in privilege mode:

public class Workspace : IDisposable 
{   
    public SPWeb AppWebPrivileged
    {
        get
        {

            if (this.appWebPrivileged == null)
            {
                lock (_myLock)
                {
                    if (this.appWebPrivileged == null)
                    {
                        SPSecurity.RunWithElevatedPrivileges(() =>
                        {
                            if (this.sitePrivileged == null)
                            {
                                this.sitePrivileged = new SPSite(this.Site.ID);
                            }
                            this.appWebPrivileged = this.sitePrivileged.OpenWeb(this.AppWeb.ID);
                            this.appWebPrivileged.AllowUnsafeUpdates = true;
                        });
                    }
                }
            }
            return this.appWebPrivileged;
        }
    }
    .....
}

Then in some method of Workspace class I can use this variable like this:

this.AppWebPrivileged.GetFile(fileName);

This works great, but currently we switch from http to https protocol. If now I call this method: this.AppWebPrivileged.GetFile(fileName); I get error: Null pointer exception.

If i put code this.AppWebPrivileged.GetFile(fileName); in same SPSecurity.RunWithElevatedPrivileges where is web opened, file can be loaded.

Is there any possibility how to open Privilege Web in one place of code, and then use this opened web in another place?

Is this pattern totaly wrong? and i have to still execute all code in privilege delegate, not only open web?

I have this problem only when using HTTPS protocol. When using HTTP, I'm possible to firstly open web in privilege mode and then use it in not privilege mode as privilege web.

1

It's not a good practice at all to open an SPWeb in an elevated context with RunWithElevatedPrivileges, close the elevated context and then continue using he SPWeb.
A much more simple approach is to open an elevated SPWeb without the use of RunWithElevatedPrivileges. You can use the SystemAccount.UserToken approach, like this:

SPSite site = new SPSite(siteStr, SPContext.Current.Site.SystemAccount.UserToken)

Also, I'm not sure about your lock here: SharePoint objects (including SPWeb) are not thread-safe and should not be used on a different thread than the one that created it. So, there should never be a need for a lock...

0

The problem was in another place. I'm opening SPSite using site ID. After open of site I looked on url stored in SPSite object. The url starts with http:// not https://. So my code is trying to open file using https prefix in http site. When i change line:

this.sitePrivileged = new SPSite(this.Site.ID);

to

this.sitePrivileged = new SPSite(this.Site.Url);

everything starts to work.

I totally agree with @Evariste that it is not good practice to use lock and also to take SPSite outside from elevated privileges. This code, created based on his answer works also great:

public class Workspace : IDisposable 
{   
    public SPWeb AppWebPrivileged
    {
        get
        {
            if (this.appWebPrivileged == null)
            {
                 if (this.appWebPrivileged == null)
                 {   
                    this.sitePrivileged = new SPSite(this.Site.Url, SPContext.Current.Site.SystemAccount.UserToken);

                    this.appWebPrivileged = this.sitePrivileged.OpenWeb(this.AppWeb.ID);
                    this.appWebPrivileged.AllowUnsafeUpdates = true;   
                }
            }
            return this.appWebPrivileged;
        }
    }
    .....
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.