Tuesday, January 30, 2018

Best Practice for disposing objects in SharePoint Development

 Using clause use to dispose common SharePoint objects like SPWeb and SPSite. This is an important issue for production environments, since not correctly disposing objects will result in excessive memory and resource usage, while over-disposing can lead to error spamming in the SharePoint log files.

Following are some of the best Practice for disposing objects in SharePoint Development


Best Practice #1: Use the Using Clause for all Sharepoint objects that implement the IDisposable interface

Example C# Coding

String str;

using(SPSite oSPsite = new SPSite("http://server"))

{

using(SPWeb oSPWeb = oSPSite.OpenWeb())

{

    str = oSPWeb.Title;

    str = oSPWeb.Url;

}

}

Best Practice #2: Use the try/catch/finally blocks. When you use try blocks, it is important to add a finally block to ensure that all objects are disposed off properly:

Example C# Coding

String str;

SPSite oSPSite = null;

SPWeb oSPWeb = null;

try

{

oSPSite = new SPSite("http://server");

oSPWeb = oSPSite.OpenWeb(..);

str = oSPWeb.Title;

}

catch(Exception e)

{

}

finally

{

if (oSPWeb != null)

  oSPWeb.Dispose();

 

if (oSPSite != null)

   oSPSite.Dispose();

}

Best Practice #3: Using Response.Redirect in the try block will never execute the finally block, so it is important, to dispose off all objects before the redirection occurs:

Example C# Coding

String str;

SPSite oSPSite = null;

SPWeb oSPWeb = null;

bool bDoRedirection = true;

try

{

oSPSite = new SPSite("http://server");

oSPWeb = oSPSite.OpenWeb(..);

str = oSPWeb.Title;

if(bDoRedirection)

{

    if (oSPWeb != null)

       oSPWeb.Dispose();

    if (oSPSite != null)

       oSPSite.Dispose();

    Response.Redirect("newpage.aspx");

}

}

catch(Exception e)

{

}

finally

{

if (oSPWeb != null)

  oSPWeb.Dispose();

if (oSPSite != null)

   oSPSite.Dispose();

}

Best Practice #4: Whenever you create an object with a new operation, the creating application must dispose it off

Example C# Coding

SPSite oSPSite = new SPSite("http://server");

... do some task ...

oSPSite.Dispose();

Or  by using clause

using(SPSite oSPSite = new SPSite("http://server"))

{

... do some task ...

}

Best Practice #5: For Site.OpenWeb method, you need to dispose it off explicitly.

Example C# Coding

String str;

SPSite oSPSite = new SPSite("http://server");

SPWeb oSPWeb = oSPSite.OpenWeb();

str = oSPWeb.Title;

str = oSPWeb.Url;

... do some task ...

oSPWeb.Dispose();

oSPSite.Dispose();

Or  by using clause

String str;

using(SPSite oSPSite = new SPSite("http://server"))

{

using(SPWeb oSPWeb = oSPSite.OpenWeb())

{

    str = oSPWeb.Title;

    str = oSPWeb.Url;

... do some task ...

}

}

Best Practice #6: An exception to the rule is that One should not explicitly dispose SPSite.RootWeb, as it is automatically disposed off.

Similarly one should not explicitly dispose SPContext.Current.Site and SPContext.Current.Web as they are handles automatically by Sharepoint and .NET framework.

Example C# bad Coding Practice

void SPContextBADPractice()

{

 SPSite siteCollection = SPContext.Current.Site;

 siteCollection.Dispose();  // DO NOT DO THIS

 SPWeb web = SPContext.Current.Web;

 web.Dispose();   // DO NOT DO THIS

}

Example C# good Coding Practice

void SPContextBestPractice()

{

 SPSite siteCollection = SPContext.Current.Site;

 SPWeb web = SPContext.Current.Web;

 // Do NOT call Dispose()

}

Best Practice #7: SPControl.GetContextSite(Context) and GetContextWeb(Context) return SPSite and SPWeb respectively, they do not need an explicit call to Dispose(), they will be disposed automatically

Example C# bad Coding Practice

void SPControlBADPractice()

{

 SPSite siteCollection = SPControl.GetContextSite(Context);

 siteCollection.Dispose();   // DO NOT DO THIS

 SPWeb web = SPControl.GetContextWeb(Context);

 web.Dispose();  // DO NOT DO THIS

}

Example C# good Coding Practice

void SPControlBestPractice()

{

 SPSite siteCollection = SPControl.GetContextSite(Context);

 SPWeb web = SPControl.GetContextWeb(Context);

 // Do NOT call Dispose()

}

Best Practice #8: SPWeb.ParentWeb  returns SPWeb, and needs to be disposed off explicitly using either Dispose() or the using clause

Example C# bad Coding Practice

void ParentWebLeak()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         SPWeb parentWeb = outerWeb.ParentWeb; // Internal reference to SPWeb parentWeb

         string sTitle = parentWeb.Title;

         string sUrl = parentWeb.Url;

         // SPWeb object parentWeb leaked

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Example C# good Coding Practice

void ParentWebBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         using (SPWeb parentWeb = outerWeb.ParentWeb) // Internal reference to SPWeb parentWeb

         {

             string sTitle = parentWeb.Title;

             string sUrl = parentWeb.Url;

         } // SPWeb object parentWeb.Dispose() automatically called

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Best Practice #9: SPWeb.Webs returns an SPWeb object, practically used in drilling down sub-sites within a Site

Example C# bad Coding Practice

void WebsLeak()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         foreach (SPWeb innerWeb in outerWeb.Webs)

         {

             // SPWeb innerWeb leak

         }

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Example C# good Coding Practice

void WebsBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         foreach (SPWeb innerWeb in outerWeb.Webs)

         {

             innerWeb.Dispose();

         }

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Best Practice #10: AllWebs[] Indexer returns SPWeb

object that needs to be disposed to avoid aggregation of memory which

can lead to memory pressure when running on a site collection with

large number of sub sites. Practically used in Enumerating or iterating all webs in a site collection.

 

Example C# bad Coding Practice

void AllWebsForEachLeakBestPractices()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         foreach (SPWeb innerWeb in siteCollection.AllWebs)

         {

              // Explicit Dispose must be called to avoid aggregation of memory

         }

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Example C# good Coding Practice

void AllWebsForEachLeakBestPractices()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb outerWeb = siteCollection.OpenWeb())

     {

         foreach (SPWeb innerWeb in siteCollection.AllWebs)

         {

             innerWeb.Dispose();   // Explicit Dispose must be called to avoid aggregation of memory

         }

     } // SPWeb object outerWeb.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

 

Example C# bad Coding Practice

void AllWebsIndexerLeak()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     SPWeb web = siteCollection.AllWebs[0];

     // SPWeb web leaked

 }  // SPSite object siteCollection.Dispose() automatically called

}

Example C# good Coding Practice

void AllWebsIndexerBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb web = siteCollection.AllWebs[0])

     {

     } // SPWeb object web.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Best Practice #11: AllWebs.Add() returns a instance of SPWeb object which needs to be disposed.

Example C# bad Coding Practice

void AllWebsAddLeak()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     SPWeb web = siteCollection.AllWebs.Add("site-relative URL");

     // SPWeb web Leaked

 }  // SPSite object siteCollection.Dispose() automatically called

}

Example C# good Coding Practice

void AllWebsAddBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))

     {

     } // SPWeb object web.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Best Practice #12: OpenWeb() returns a SPWeb object which needs to be disposed.

Example C# bad Coding Practice

void OpenWebLeak()

{

 using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())

 {

     // SPSite leaked !

 } // SPWeb object web.Dispose() automatically called

}

Example C# good Coding Practice

void OpenWebBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

     using (SPWeb web = siteCollection.OpenWeb())

     {

     } // SPWeb object web.Dispose() automatically called

 }  // SPSite object siteCollection.Dispose() automatically called

}

Best Practice #13:new SPSite() - Instantiating SPSite objects with the new operator needs to be disposed.

Example C# bad Coding Practice

void CreatingSPSiteLeak()

{

 SPSite siteCollection = new SPSite("http://moss");

 // siteCollection leaked

}

Example C# good Coding Practice

void CreatingSPSiteExplicitDisposeBestPractice()

{

 SPSite siteCollection = new SPSite("http://moss");

 siteCollection.Dispose();

}

void CreatingSPSiteWithAutomaticDisposeBestPractice()

{

 using (SPSite siteCollection = new SPSite("http://moss"))

 {

 } // SPSite object siteCollection.Dispose() automatically called

}


Thank you very much

          Fahadullah Karimi

         SharePoint Specialist


List of all web parts used on SharePoint 2013 pages using PowerShell How to Save Site as Template in Publishing Site Template in SharePoint 2013