Monday, March 15, 2010

Best Coding Practices For Using Sharepoint Object Model

Content:
  • Introduction
  • Using objects in event receivers
  • Disabling Event Firing
  • Working with folders and lists
  • Using SPQuey Objects
  • Dispose WSS Objects
  • Subfolder creation in a list 
Introduction:
WSS provides a highly structured server-side object model that makes it easy to access objects that represents the various aspects of a SharePoint Web site. From higher-level objects, we can drill down through the object hierarchy to obtain the required object to be used in our code.
Diagram depicting the WSS site architecture in relation to the collections and objects of the Microsoft. SharePoint namespace is as follows:

While creating a new application or to improve the performance, extensibility and scalability of existing application it is important to understand how to make the SharePoint object model work efficiently, and how to apply general programming techniques to the SharePoint platform specifically. These common best coding practices can make it easier to design our applications correctly, find and fix problem areas in our code, and avoid known pitfalls of using the SharePoint object model.

Using Objects in Event Receivers:

SPWeb, SPSite, SPList, or SPListItem objects should not be instantiated within an event receiver. Within Event Receivers instead of using these objects event properties should be used otherwise following problems may occur:

• They incur significant additional roundtrips to the database. (One write operation can result in up to five additional roundtrips in each event receiver.)

• Calling the Update method on these instances can cause subsequent Update calls in other registered event receivers to fail.

Disabling Event firing:
Event handlers are fired synchronously or asynchronously for every addition, update, and deletion etc. if also that is not required from different code execution and it can cause performance degradation and unnecessary execution of event handlers code. So these event handlers must be disabled whenever not required. Code for this is:

public static void EnableEventFiring()
{
SetEventFiringSwitch(false);
}
public static void DisableEventFiring()
{
SetEventFiringSwitch(true);
}
private static void SetEventFiringSwitch(bool value)
{
PropertyInfo pi = EventManagerType.GetProperty(_eventFiringSwitchName, System.Reflection.BindingFlags.Static
System.Reflection.BindingFlags.NonPublic);
pi.SetValue(null, value, null);
}
private static bool GetEventFiringSwitchValue()
{
PropertyInfo pi = EventManagerType.GetProperty(_eventFiringSwitchName, System.Reflection.BindingFlags.Static
System.Reflection.BindingFlags.NonPublic);
object val = pi.GetValue(null, null);
return (bool)val;
}
private static Type GetEventManagerType()
{
_eventManagerType = typeof(SPList).Assembly.GetType(_className, true);
return _eventManagerType;
}
Working with folders and lists:
Working with large lists and folders needs conventional design change to optimize performance which is as follows:

  • Instead of using SPList.Items use SPList.GetItems(SPQuery query) and apply appropriate filter on query to make it more efficient. If list contains more than 2000 items then paginate the list in increments of no more than 2000 items.
  • Instead of using SPList.Items.GetItemById use SPList.GetItemById.
  • While adding a new item in a list instead of using SPList.Items.Add use SPList.GetItems(q).Add where q is empty query. Code for this is:- const
string EmptyQuery = "0";
SPQuery q = new SPQuery { Query = EmptyQuery };
SPListItem item = List.GetItems(q).Add();
  • Do not enumerate entire SPList.Items collections or SPFolder.Files collections.
  • While retrieving SPList object instead of getting it by using list’s name use its GUID or URL of the list.
Using SPQuery Objects:
When SPQuery returns large result sets than that can cause performance problem so points to keep in mind while designing query are as follows:
  • Use RowLimit between 1 and 2000 for SPQuery and paginate through the list if required.
  • If List Item URL is known than query list by using FileRef like SPWeb.GetListItem(string strUrl, string field1, params string[] fields).
  • Whenever possible use indexed columns in where clause of SPQuery.

Dispose WSS Objects:
WSS object model contains objects that implement the IDisposable interface. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. It is not known that when garbage collector will execute. Furthermore, the garbage collector has no knowledge of unmanaged resources. So Dispose method of this interface should be explicitly called to release unmanaged resources in conjunction with the garbage collector.

SPSite and SPWeb objects are managed objects but use unmanaged code and memory to do majority of their work. The managed part of the object is much smaller than the unmanaged part. Because the smaller managed part does not put memory pressure on the garbage collector, the garbage collector does not release the object from memory in a timely manner. The object's use of a large amount of unmanaged memory can cause some of the unusual behaviors like poor performance, application crash, high memory use of IIS worker process. Calling applications that work with IDisposable objects in Windows SharePoint Services must dispose of the objects when the applications finish using them. We should not rely on the garbage collector to release them from memory automatically.
We can employ certain coding techniques to ensure object disposal. These techniques include using the following in our code:
  • Dispose method
  • using clause
  • try, catch, and finally blocks
Subfolder Creation in a list:
If list size exceeds 2000 items then Microsoft recommends having subfolders for every 2000 items in a list. Then use SPQuery.ViewAttributes = "Scope=\"Recursive\"" for querying data through SPQuery and if possible than query only from subfolder by giving its name.

Thursday, March 4, 2010

Context sensitive help in SharePoint

Context sensitive help is key part of any product now Days. Product companies don’t want their customers to search for a particular help in entire help system and it becomes really difficult in case of online help where you may want to redirect your customer to some online help article

You must have seen such scenarios in many Microsoft products. The one I can remind now is code analysis tool or FxCop
Below is the sample steps of context sensitive help implemented in a SharePoint product, which can be implemented in ASP.NET or any other technology

Step 1: define a content placeholder in master page of the application (as top right corner the default location in SharePoint)

Step 2: now from each page add an image button on which you will attach a javascript function to call help page. Add any standard help image on this button

Step 3: prepare an xml file on which define key value pair for each page.where key will be the page context and value will be the respective URL

Step 4: onload of each page attach a java script function to help image button onclick event which will find the URL from defined xml file

Step 5: prepare a separate help system such as .chm file and publish help content as per the associated links

Step 6: host all the pages in the web server incase of SharePoint I posted all these files which include .htm\.jpg\.css etc in a form library

Step 7: run the application and you will be able to access your help system in context of the current page

I will post the respective code for this soon
Reach me for more detail explanation.