Search This Blog

Thursday, January 1, 2015

SharePoint 2013 - Server Object Model

Overview

As you might already know that the SharePoint 2013 is built upon .Net 4.5 framework and Asp.Net. 
Therefore, the SharePoint infrastructure provides a rich .Net object model for developing solutions
 using compatible server side language like (C#, VB.NET etc). This Server Object Model comprises a 
set of namespaces and classes which must run on a SharePoint server because this is the only server
 on which the Server Object Model runs; it has some dependencies that are satisfied only on servers in a
 SharePoint farm.

Startup Environment
  • In Visual Studio, the Target Framework will be set to “.NET Framework 4.5” by default. 
  • Also, Platform Target setting in the Build configuration tab of the project will be set to “Any CPU” by 
  • default. Microsoft SharePoint 2013 works on 64-bit machines only.
  • The "Microsoft.SharePoint.dll" is the main server object model assembly which comprises of  the 
  • following 2 important namespace.
    • "Microsoft.SharePoint" - Consists of classes and members for developing solution in a top 
    • level SiteCollection, its subsites or lists (eg: SPSite, SPWeb etc).
    • "Microsoft.SharePoint.Administration" - Consists of classes and members for developing
    •  solutions at an admistrative level. (eg: SPFarm, SPServer etc)
  • When you create a SharePoint project in Visual Studio 2012, the "Microsoft.SharePoint.dll" assembly 
  • is automatically referenced.
  • On the other hand, for windows Console\WinForm applications, you need to reference "
  • Microsoft.SharePoint.dll" explicitly. You can find it, along with many of the other assemblies, in the SharePoint15_Root\ISAPI folder.
Server Architecture
The following figure gives you a clear idea about the SharePoint Server Architecture with reference to "Microsoft.SharePoint.Administration" namespace.

From the above figure you can summarize the following point:
  • The "SPFarm" object is the highest object within the SharePoint Foundation object model hierarchy.
  • Each "SPServer" object represents a physical server computer. 
  • Each "SPService" object represents a logical service installed in the server farm.The
  •  WebApplications property gets the collection of Web applications that run the service.
  • An "SPWebService" object provides access to configuration settings for a specific logical service 
  • or application
  • Each "SPWebApplication" object represents a Web application hosted in an Internet Information 
  • Services (IIS) Web site. The Sites property gets the collection of site collections within the Web
  •  application, and the ContentDatabases property gets the collection of content databases used in the 
  • Web application.
  • The Sites property gets the collection of site collections within the Web application, and the 
  • ContentDatabases property gets the collection of content databases used in the Web application.
  • An "SPContentDatabase" object inherits from the "SPDatabase" class and represents a database 
  • that contains user data for a Web application.
Site Architecture
The following figure will give you a better idea about the SharePoint Site Collection Architecture with
 reference to "Microsoft.SharePoint" namespace.


From the above figure you can easily summarize the following points:
  • The "SPSite" object represents a Site Collection. 
  • Each site collection includes any number of "SPWeb" objects, and each object has members that
  •  can be used to manage a site, including its template and theme, as well as to access files and folders 
  • on the site.
  • The "SPListCollection" object that represents all the lists in the site.
  • Each "SPList" object has members that are used to manage the list or access items in the list. 
  • The "SPFieldCollection" object that represents all the fields, or columns, in the list, and the Items 
  • property returns an "SPListItemCollection" object that represents all the items, or rows, in the
  •  list.
  • Each "SPField" object has members that contain settings for the field.
  • Each "SPListItem" object represents a single row in the list.
Conclusion
This is just a basic overview of overall Server Object Model architecture which is very much similar to 
SP 2007 and SP 2010. 


Object Hierarchy

Following is the hierarchy in which the classes supporting Server OM reside.



Object Hierarchy - Main Members
  • SPFarm
  • SPServer
  • SPService
  • SPWebApplication
  • SPSite
  • SPWeb
  • SPList
  • SPListItem

SPFarm
SPFarm class belong to the "Microsoft.SharePoint. Administration" namespace refers to a complete Farm.
 We can create a new farm from scratch or connect to an existing farm.
Connecting to Farm
1) Connect to Existing Farm: (the most common scenario), you provide a SQL Server connection string
 and the Farm’s secret passphrase to the public static Open() method.
public static SPFarm Open(SqlConnectionStringBuilder connectionString, 
SecureString passphrase)
Where, The connection string corresponds to the Farm configuration database that is defined while
 configuring the Farm using the SharePoint 2013 Products Configuration Wizard. It can also be found in 
the system registry at:
HKLM\Software\Microsoft\Shared Tools\Web Server Extensions\14.0\Secure\ConfigDB\dsn.
2) Connect to Local Farm: we can directly connect to a local Farm, using the static property
SPFarm objFarm = SPFarm.Local 
OR 
SPFarm objFarm = SPContext.Current.Site.WebApplication.Farm
Inside SPFarm
1) SPFarm contains global settings for all the servers, services, and solutions that are installed in a server 
farm.
2) Its Servers property contains a collection representing all the servers in the environment, and similarly 
the Services property has a collection representing all the services.
3) The SPFarm class has three child classes:
SPServer, which represents a single server within the farm;
SPService, which gives access to the farm’s services; and
SPSolution, which is used to deploy something to the farm.

SPServer
SPServer represents a server in a SharePoint farm.
We can get a current reference to the SPServer:
foreach (SPServiceInstance objService in SPServer.Local.ServiceInstances)
Console.Writeline("objService.TypeName");
Or, Instantiate any server’s object in a specific farm
SPServer objServer = new SPServer(“MyFarmServer″);

SPService
There are numerous services such as web services or Search Services running inside a 
SharePoint Server.Each of these services can be referenced through SPServices Object.
SPServiceCollection ObjServiceCollection = SPFarm.Local.Services;
foreach (SPService service in ObjServiceCollection){}

SPWebApplication
In object model, SPWebApplication class refers to each Web application configured in SharePoint.
 It is the topmost object in the site hierarchy.
SPWebApplication objSPWebApplication = SPContext.Current.Site.WebApplication;
Or
SPWebApplication objSPWebApplication = new SPSite("http://home:3000/")
.WebApplication;

SPSite
The SPSite represents a site collection. To access an SPSite instance, you can create it using one of the 
following available constructors:
public SPSite(Guid id);
public SPSite(string requestUrl);
public SPSite(Guid id, SPUrlZone zone); // public enum SPUrlZone {Default,Intranet,Internet,Custom,Extranet}
public SPSite(Guid id, SPUserToken userToken); // SPUserToken is the token for a valid SharePoint user.
public SPSite(string requestUrl, SPUserToken userToken);
public SPSite(Guid id, SPUrlZone zone, SPUserToken userToken);

We can create a new Site instance as follows:
SPSite  objSPSite = new SPSite("http://home:3000/");
 Or
SPSite  objSPSite = SPContext.Current.Site;

Note: When you create an SPSite instance using SPUserTokenyou can impersonate the user who owns 
that token rather
 than the current user. You can import an SPUserToken instance from a previously exported array of
 bytes, or you can create one from a generic System.Security.Principal.IIdentity

SPWeb
The SPweb class represent a website or sub-site in a site collection. This class does not have a public 
constructor. The only way to obtain a reference to a website is through its parent SPSite. The SPSite 
class provides the OpenWeb() method which has the following overloads:

public SPWeb OpenWeb();
public SPWeb OpenWeb(Guid gWebId);
public SPWeb OpenWeb(string strUrl);
public SPWeb OpenWeb(string strUrl, bool requireExactUrl);

You can use an SPWeb reference to navigate the contents of the website:-
SPSite site = new SPSite("http://home:3000/");
SPWeb web = site.OpenWeb();
Console.WriteLine(web.Title);

You can also use an SPWeb reference to read or change its configuration.
SPSite site = new SPSite("http://home:3000/");
SPWeb web = site.OpenWeb("Samples");
web.Title = web.Title + " - Changed by code!";
web.Update();

Note: While working with the Server Object Model, you are reading and changing an in-memory 
representation of the current object. Thus, any changes you make will not be applied to the database 
unless you explicitly request the object to persist its state using the Update method.

SPList
SPList corresponds to a single list instance, whether that is a list of items or a document library.
SPSite site = new SPSite("http://home:3000/");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["MyList"];

Applying Filters on List
SPQuery class is used for  applying  filters on a list while retrieving items. Commonly used properties of
 SPQuery are:-

  1. Query – Filtering and sorting of data based on conditions.
  2. ViewFields – Retrict the number of fields to be retrieved.
  3. ViewFieldsOnly – If set true, remove the default fields (ID, Created, Modified) in ViewFields.

Sample Code
SPWeb objWeb = SpContext.Current.Web;
SPList objList = objWeb.Lists[“Products"];
SPQuery objQuery = new SPQuery();
objQuery.Query = "<Where><Eq><FieldRef Name='P_Category' /><Value Type='Lookup'>"
 + strCategory + "</Value></Eq></Where>";
oQuery.ViewFields = "<FieldRef Name='Title' /><FieldRef Name='Price' />
<FieldRef Name='Description' />";
oQuery.ViewFieldsOnly = true;
SPListItemCollection objColl = objList.GetItems(oQuery);
gvwProducts.DataSource = objColl.GetDataTable();
gvwProducts.DataBind();

Handling Document Libraries
Whenever you use an SPList instance, which corresponds to a document library, you can cast that
 instance to an SPDocumentLibrary type. When you need to enumerate the files contained in a document
 library, you can browse the SPListItem elements of the list, accessing their File property, which is of type
 SPFile.
SPSite site = new SPSite("http://home:3000/");
SPWeb web = site.OpenWeb();
SPDocumentLibrary docLibrary = web.Lists["MyDocs"] as SPDocumentLibrary;
foreach (SPListItem item in docLibrary.Items) {
  Console.WriteLine("{0} - {1}",item.File.Name,item.File.Length);}


SPListItem
SPListItem defines a reference to a specific item of a list.
SPList list = web.Lists["MyList"];
foreach (SPListItem item in list.Items) {
Console.WriteLine(item.Title);}

Sample Code : Programmatic drill down form Farm to List
The following codes drills down the various object in Server Object Model and displays the hierarchy 
from Farm to ListItems.
Console.ForegroundColor = ConsoleColor.Green;
Console.BufferHeight = 1000;
//Get local farm
SPFarm farm = SPFarm.Local;
Console.Write(farm.Id.ToString("N").ToLower());
//loop Services
foreach (SPService service in farm.Services)
{
    //find WebService
    if (service is SPWebService)
    {
        SPWebService webService = (SPWebService)service;
        //Loop WebApps
        foreach (SPWebApplication webApp in webService.WebApplications)
        {
            Console.Write(webApp.Id.ToString("N").ToLower());
            //Loop Site Collections
            foreach (SPSite site in webApp.Sites)
            {
                Console.Write(site.ID.ToString("N").ToLower());
                //Loop Sites
                foreach (SPWeb web in site.AllWebs)
                {
                    Console.Write(web.ID.ToString("N").ToLower());
                    //Loop Lists
                    foreach (SPList list in web.Lists)
                    {
                        Console.Write(list.ID.ToString("N").ToLower());
                        //Loop Items
                        foreach (SPListItem item in list.Items)
                        {
                            Console.Write(item.UniqueId.ToString("N").ToLower());
                        }
                    }
                    web.Dispose();
                }
                site.Dispose();
            }
        }
    }
}

SharePoint 2013 - Coding standards and best practices
In this post we will go through some of the coding standards and best practices that have been 
recommended by Microsoft for SharePoint 2013.

Using SharePoint Data and Objects Efficiently
Caching is one good way to improve system performance. However, you must weigh the benefits of
 caching against the need for thread safety. Additionally, you should not create certain SharePoint
 objects within event receivers because this will cause performance problems related to excessive 
database calls.

1) Caching Data and Objects
Many developers use the Microsoft .NET Framework caching objects (for example, 
System.Web.Caching.Cache) to help take better advantage of memory and increase overall system
 performance. But many objects are not "thread safe" and caching those objects can cause applications
 to fail and unexpected or unrelated user errors.

2) Caching SharePoint Objects That Are Not Thread Safe 
You might try to increase performance and memory usage by caching SPListItemCollection objects
 that are returned from queries. In general, this is a good practice; however, the SPListItemCollection
 object contains an embedded SPWeb object that is not thread safe and should not be cached.
 For example, assume the SPListItemCollection object is cached in a thread. As other threads try to
 read this object, the application can fail or behave strangely because the embedded SPWeb object is
 not thread safe. For more information about the SPWeb object and thread safety, see the 
Microsoft.SharePoint.SPWeb class. The guidance in the following section describes how you can 
prevent multiple threads from attempting to read the same cached object.

3) Understanding the Potential Pitfalls of Thread Synchronization
You might not be aware that your code is running in a multithreaded environment (by default, 
Internet Information Services, or IIS, is multithreaded) or how to manage that environment.
 The following example shows the code some developers use to cache 
Microsoft.SharePoint.SPListItemCollection objects.

Bad Coding Practice
Caching an Object That Multiple Threads Might Read
public override void ItemDeleting(SPItemEventProperties properties)
{
using (SPSite site = new SPSite(properties.WebUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[properties.ListId];
SPListItem item = list.GetItemByUniqueId(properties.ListItemId); 
// Operate on item.
}
}
}

Applying a Lock
Checking for null
// Retrieve SPWeb and SPListItem from SPItemEventProperties instead of 
from a new instance of SPSite.
SPWeb web = properties.OpenWeb(); // Operate on SPWeb object.
SPListItem item = properties.ListItem// Operate on item.


Working with Folders and Lists
When folders and lists grow in size, custom code that works with them needs to be designed in ways
 that optimize performance. Otherwise, your applications will run slowly and even cause timeouts to occur.
 The following recommendations for addressing performance concerns while working with large folders and
 lists are based on the test results reported in Steve Peschka's white paper, Working with Large Lists in Office
 SharePoint Server 2007.

1)  Do not use SPList.Items.SPList.Items 
Selects all items from all subfolders, including all fields in the list. Use the following alternatives for
 each use case.
Retrieving all items in a list Use SPList.GetItems(SPQuery query) instead. Apply filters, if appropriate, 
and specify only the fields you need to make the query more efficient. If the list contains more than 
2,000 items, you will need to paginate the list in increments of no more than 2,000 items. 
The following code example shows how to paginate a large list. Getting items by identifier Instead 
of using SPList.Items.GetItemById, use SPList.GetItemById(int id, string field1, params string[] fields). 
Specify the item identifier and the field that you want.

2) Do not enumerate entire SPList.Items collections or SPFolder.Files collections.
Accessing the methods and properties that are listed in the left column of the following table will 
enumerate the entire SPList.Items collection, and cause poor performance and throttling for large lists. Instead,
use the alternatives listed in the right column.


3) Whenever possible, acquire a reference to a list by using the list's GUID or URL as a key.
You can retrieve an SPList object from the SPWeb.Lists property by using the list's GUID or display
 name as an indexer. Using SPWeb.Lists[GUID] andSPWeb.GetList(strURL) is always preferable to using 
SPWeb.Lists[strDisplayName]. Using the GUID is preferable because it is unique, permanent, and 
requires only a single database lookup. The display name indexer retrieves the names of all the lists
 in the site and then does a string comparison with them. If you have a list URL instead of a GUID, 
you can use the GetList method to look up the list's GUID in the content database before retrieving
 the list.

4) Avoid creating and destroying objects unnecessarily in code
Avoid creating and destroying objects unnecessarily in code, as this may require that extra queries 
be made against the database and may even involve code that is incorrect.
In the following example, separate objects for the Tasks list must be instantiated each time the indexer
 is used to set properties and the method for updating is called. This is not a recommended practice.

Bad Practice
SPWeb myWeb = SPContext.Current.Web; 
myWeb.Lists["Tasks"].Title = "List_Title"; 
myWeb.Lists["Tasks"].Description = "List_Description"; 
myWeb.Lists["Tasks"].Update(); 

Good Practice
SPWeb myWeb = SPContext.Current.Web; 
SPList myList = myWeb.Lists["Tasks"]; 
myList.Title="List_Title"; 
myList.Description="List_Description"; 
myList.Update();

Note: 
a) The object models in the Microsoft.SharePoint assembly optimize performance and minimize the
 number of SQL queries that are made. However, to monitor code performance, it is recommended
 that you use the SQL Profiler.
b) To return a single item from a collection, always use a Get* method when one is provided through
 a parent object, instead of iterating through the entire collection and using an indexer. 

5) Handling large folders and lists
When the size of folders and lists increases, you must design custom code that works with them to 
optimize performance. Otherwise, your applications will run slowly and can cause service or 
page load timeouts. The two primary areas for concern when handling large folders and lists are 
the following:
Query throttling, which can cause the behavior of your code to change in unexpected and
 unpredictable ways over time as your site evolves and your queries begin to return items that exceed 
the query threshold.
Efficient retrieval of items from large folders and lists.

6) Throttling for Large List Queries
Microsoft SharePoint Foundation 2013 and Microsoft SharePoint Server 2013 apply a default query
 threshold of 5,000 items. Any custom code that relies on query result sets that can exceed this
 maximum will not perform as expected. Queries on lists consisting of more than 5,000 items that 
include fields that are not indexed in their query conditions will also fail, because those queries must
 scan all rows in a list. Follow the steps listed below to view and increase this limit or to enable the
 object model to override the limit:
To view and increase this threshold or to enable the object model to override the threshold
On the Central Administration site, under Application Management, click Manage Web Applications.
Click General Settings, and then click Resource Throttling.
View and update the threshold or allow the object model to override the limit.

7) Deleting Multiple Versions of a List Item
When you delete multiple versions of a list item, use the DeleteByID method; do not use the Delete
 method. You will experience performance problems if you delete eachSPListItemVersion object from
 an SPListItemVersionCollection object. The recommended practice is to create an array that contains 
the ID properties of each version and then delete each version by using the 
SPFileVersionCollection.DeleteByID method. The following code examples demonstrate both the
 approach that is not recommended and the recommended approach to deleting all versions of the
 first item of a custom list.

Bad Coding Practice
Deleting each SPListItemVersion object
SPSite site = new SPSite("site url"); 
SPWeb web = site.OpenWeb(); 
SPList list = web.Lists["custom list name"]; 
SPListItem item = list.GetItemById(1); 
SPListItemVersionCollection vCollection = item.Versions
ArrayList idList = new ArrayList(); 
foreach(SPListItemVersion ver in vCollection
 idList.Add(ver.VersionId); 
foreach(int verID in idList
 SPListItemVersion version = vCollection.GetVersionFromID(verID); 
try 
 version.Delete(); 
catch (Exception ex) 
 MessageBox.Show(ex.Message); 
}

Good Coding Practice
Deleting each version of a list item by using the SPFileVersionCollection.DeleteByID method
SPSite site = new SPSite("site url"); 
SPWeb web = site.OpenWeb(); 
SPList list = web.Lists["custom list name"]; 
SPListItem item = list.GetItemById(1); 
SPFile file = web.GetFile(item.Url); 
SPFileVersionCollection collection = file.Versions
ArrayList idList = new ArrayList(); 
foreach (SPFileVersion ver in collection) 
 idList.Add(ver.ID); 
foreach (int verID in idList
try 
 collection.DeleteByID(verID); 
catch (Exception ex) 
 MessageBox.Show(ex.Message); 
}

8) Using SPQuery Objects
SPQuery objects can cause performance problems whenever they return large result sets.
 The following suggestions will help you optimize your code so that performance will not suffer
 greatly whenever your searches return large numbers of items.
Do not use an unbounded SPQuery object. An SPQuery object without a value for RowLimit will 
perform poorly and fail on large lists. Specify a RowLimit between 1 and 2000 and, if necessary,
 page through the list.
Use indexed fields. If you query on a field that is not indexed, the query will be blocked whenever
 it would result in a scan of more items than the query threshold (as soon as there are more items in 
the list than are specified in the query threshold). Set SPQuery.RowLimit to a value that is less than
 the query threshold.
If you know the URL of your list item and want to query by FileRef, use
 SPWeb.GetListItem(string strUrl, string field1, params string[] fields)instead.

Using Web Controls
When you inherit and override controls in the Microsoft.SharePoint.WebControls namespace,
 remember that SharePoint Web controls are templated controls. Unlike Microsoft ASP.NET Web 
controls, they are defined and rendered with templates instead of with the CreateChildControls method.
 Instead of having a thickCreateChildControls method that uses the new operator to create child
 controls, perform most child control creation and rendering by using the rendering templates that 
are referenced in the Template, AlternateTemplate, DisplayTemplate, CustomTemplate, and 
AlternateCustomTemplate properties of the SharePoint Web control. SharePoint Web controls do
 inherit the CreateChildControls method, but that method should typically do little or nothing
 beyond calling the parent control's CreateChildControlsmethod and perhaps a bit of "final polish"
 rendering, such as assigning default values to child control properties in New mode or assigning
 the current values in Edit mode.

Creating Timer Jobs
Design your timer jobs so that they consist of small, manageable pieces. Because administrators and
 other events, such as system restarts, can stop timer jobs, you can minimize the amount of rework
 after any interruption by breaking timer jobs into small pieces of work.

Avoiding Unnecessary Construction of SPWeb and SPSite Objects
An SPWeb or SPSite object can occupy a lot of memory. Avoid constructing objects of these types
 simply to get a reference to a parent object. Instead, to get a reference to a web application, use 
the static SPWebApplication.Lookup(Uri) method, and pass it a Uri object that is created with the
 URI of the web application. You can then get a reference to the farm by using the Farm property of
 the web application object. (You can get a reference to a remote farm by using the static Open(String) 
method.) TheContentDatabases property of the web application object contains a collection of the
 content databases in the web application. You can get a reference to a particular content database 
through this property if you know its index in the collection. For more information, see the reference
 topic for the SPContentDatabaseCollection class. The following code illustrates some of these points.
SPWebApplication webApplication = SPWebApplication.Lookup(new Uri("http://localhost/"); 
SPFarm farm = webApplication.Farm
SPContentDatabase content = webApplication.ContentDatabases[0];

File Naming Restrictions 
For security reasons, SharePoint Foundation reads files in the %ProgramFiles%\
Common Files\Microsoft Shared\web server extensions\15\TEMPLATE directory tree only if
 their names are composed of ASCII letters, numbers, periods, underscores, or dashes. In addition, 
file names cannot contain two or more consecutive periods. For example:
Following are permitted file names:
a) AllItems.aspx
b) Dept_1234.doc
c) Long.Name.With.Dots.txt
The following are not permitted file names:
a) Cæsar.wav
b) File Name With Spaces.avi
c) Wow...ThisIsBad.rtf
d) 揵.htm

Accessing Web and Site Objects

1) Get Current Site details using SPSite 
 SPSite oSiteCollection = SPContext.Current.Site;

2) Get Current Web details using SPWeb 
 SPWeb oWebSite = SPContext.Current.Web;

3) When your code is contained in an .aspx file or the "code behind" in an .aspx.cs file,
 you can use methods to get the SPWeb.
SPWeb oWebSite = SPControl.GetContextWeb(Context);  where Context = System.Web.UI.Page.Context

4) To get reference of the current web object from .aspx page that is inherited from
 LayoutsPageBase is :
SPWeb oWebSite = this.Web;

5) Use the Microsoft.SharePoint.SPSite.AllWebs property to obtain a reference to a 
Web site other than the current one. 
SPWeb oWebSite = SPContext.Current.Site.AllWebs["myOtherSite"];

6) Get reference of server farm or current physical server : 
SPFarm oFarm = SPFarm.Local;


Access external systems
When the data source is a Web service or database, consider using the Business Data Catalog (BDC) 
for SP 2007 and Business Connectivity Services (BCS) for SP 2013.
SharePoint Databases
Do not make calls directly to the SharePoint content and configuration databases.
Packaging
Structure your code project so that solution packaging is integrated into the project

Dispose Objects
We should not dispose any SPWeb, SPSite object create using SPContext.Current.Site,
 SPContext.Current.Web, SPControl.GetContextWeb(Context), this.Web
We should explicitly dispose of references to objects obtained through the AllWebs property
The code should dispose any SPSite or SPWeb object obtained by using a constructor.
Do not dispose dispose of the SPWeb.ParentWeb
The SPWeb.Webs property returns an SPWebCollection object. The SPWeb objects in this collection 
must be disposed.
The SPWeb.Webs.Add method (or Add) creates and returns a new SPWeb object. You should dispose
 of any SPWeb object returned from this method call.
If the object is obtained from the SharePoint context objects (GetContextSite method and
 GetContextWeb method), the calling application should not call the Dispose method on the object.
You should still dispose of an object that is created from these objects, for example, if a Web site is
 opened from an SPSite object that you obtained by using the GetContextSite method.

Wrong Way
void CombiningCallsLeak()
{
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
        // ... New SPSite will be leaked.
    } // SPWeb object web.Dispose() automatically called.
}

Right Way
void CombiningCallsBestPractice()
{
    using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        //Perform operations on site.
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

Exception Handling in SharePoint

1. Avoid empty Catch blocks
All the errors should be reported using error logging functionality, if not handled sufficiently.
Wrong Way
try
{
    // code
}
catch { }

2. Use throw; if you’re going to throw an exception
Wrong Way
try
{
    // code
}
catch (Exception ex)
{
    throw ex;
}
Right Way
try
{
    // code
}
catch
{
    throw;
}

3. Handle the specific exception wherever possible
Right Way
try
{
    spList = spWeb.GetList("/Path/List");
}
catch (FileNotFoundException ex)
{
    // handle exception
}
catch (ArgumentException ex)
{
    // handle exception
}

4. Try to check condition before it throws exception
Wrong Way
try
{
    myString = listItem["MyField"].ToString();
}
catch (Exception ex)
{
    // handle exception
}
Right Way
if (String.IsNullOrEmpty(listItem["MyField"]))
{
    myString = listItem["MyField"].ToString();
}

6. Use an appropriate form of logging exception.
 The most important takeaway is to ensure that the errors are logged. The 2 most logical locations 
to log the errors would be the ULS or Event Log, however this may not always be appropriate. 
If these locations aren’t regularly monitored or accessible by the people who need to know about
 the errors, then it is essentially no better than swallowing the errors in the first place. Email, CRM, a
 database or even a SharePoint list are other potential locations that could be more accessible.
 Logging to a file on the file system makes little sense seeing if that is an accessible option you could 
just use the ULS.

7. Use a custom error page.
Nothing looks worse on a public facing internet site or even an intranet application than when you 
get the SharePoint default error page. Wherever possible you should display a user friendly message 
rather than an ugly generic error page.


No comments:

Post a Comment