Tuesday, May 15, 2012

Docflow Timer Job for Document Synch..

Purpose: The purpose of this timer job to update the status of deliverable of Docflow from the GDMS systems in timely fashion. On a particuler time it takes synch the docflow document status from the GDMS System.

Code flow and functionality..
override

There are two functions defined in the basic functionality one for documentSynch and other for DocumentContribution synch.. Document synch pull all the items from the Docflow Calender list except Completed and Discontinued, takes the releated document from the Document list and update the status. while documentcontribution picks the records from the Docuemnt list.

using the web application we picks site and using the site we pick web.
objSPListItemCollection is the collection of items from Docflow calender except Completed and Discontinued.

SynchronizeDocument(currentSPweb, objSPListItemCollection);

Loop through each item of objSPLIstItemCollection check the intiationstart of calender item if it is null then assign to new DateTime(1900,1,1) otherwise pick from calender list item and put the calender status to the local variable status.
actualInitStartDate =

//now get the document list item heredocListItem =
The common function used to get the document of the particuler calenderlist item in which we pass the calenderListItemID.
DocumentDAO.GetDocumentListItemByCalendarID(currentSPweb.Site.Url, CalenderListItem.ID.ToString());
The DocListItem is getting from Document List using the SPQuery Object.

If DocList item is not null then we pull the following fields values to access the data from GDMS.
 Convert.ToString(docListItem[GlobalConstants.COLUMN_GDMS_R_OBJECT_ID]);Convert.ToString(docListItem[GlobalConstants.COLUMN_GDMS_I_CHRONICLE_ID]);
strObjectID =
strChronicleID =

In StrNewObjectID it gets the versionID to communicate from the GDMS web service passing the crediantials using the cryptography format. first getting the applicable versionID to communicate from GDMS web service and passing this to the GDMS database and apply the query to find this chronicleID.. if it find then assign it to the strNewObjectID.
string

Now apply the function, If strObjectID not equel to strNewObjectID apply function
if
{

}

In the above function only two fields are updating one is  gdms_r_object_id and other is GDMS_x0020_Link

//now get GDMS document object based on object idobjGDMSObject =

Now Check If objGDMSObject is not equal to null  then

If  the status of objGDMSObject is "In Review" then set the
// set the list item status to review
then set the status of following fields
CalenderListItem[
updatedStatus =
CalenderListItem[
iscalendarChange =
GlobalConstants.COLUMN_DOCFLOW_STATUS] = Enumerators.DocStatus.Review.ToString();Enumerators.DocStatus.Review.ToString();GlobalConstants.COLUMN_ACTUAL_APPROVAL_START_DATE] = null;true;
GDMSDataBaseDAO.GETDGMSObject(currentSPweb.Site.Url, strNewObjectID);
(strObjectID != strNewObjectID)CalendarDAO.UpdateDocumentObjectInfo(docListItem, strNewObjectID);
queryNewObject = "select r_object_id from pfe_document where i_chronicle_id = '" + strChronicleID + "';";
void Execute funtion : 

and setting the start date from the //set the start date from audit trail event

//if status = pending approval
update the status
//always update latest the Approval start date from audit trail event
// set earliest review start date

else
|| objGDMSObject.Status.Equals(
|| objGDMSObject.Status.Equals(
|| objGDMSObject.Status.Equals(

Updating followings fields
CalenderListItem[
CalenderListItem[
CalenderListItem[
CalenderListItem[


If GDMS status is unknown else condition
CalenderListItem[
updatedStatus =
CalenderListItem[
iscalendarChange =

{
dtReviewStartDate =

{
CalenderListItem[
}
GlobalConstants.COLUMN_DOCFLOW_STATUS] = Enumerators.DocStatus.Review.ToString();Enumerators.DocStatus.Review.ToString();GlobalConstants.COLUMN_ACTUAL_APPROVAL_START_DATE] = null;true;if (String.IsNullOrEmpty(Convert.ToString(CalenderListItem[GlobalConstants.COLUMN_ACTUAL_REVIEW_START_DATE])))GDMSDataBaseDAO.GetObjectReviewStartDate(currentSPweb.Site.Url, objGDMSObject, actualInitStartDate);if (dtReviewStartDate.HasValue)GlobalConstants.COLUMN_ACTUAL_REVIEW_START_DATE] = dtReviewStartDate;
GlobalConstants.COLUMN_ACTUAL_REVIEW_START_DATE]
GlobalConstants.COLUMN_ACTUAL_APPROVAL_START_DATE]
GlobalConstants.COLUMN_ACTUAL_RAD_HANDOVER_DATE]
GlobalConstants.COLUMN_DOCFLOW_STATUS]
if (objGDMSObject.Status.Equals(GlobalConstants.GDMS_DOC_STATUS_FIT_FOR_USE)GlobalConstants.GDMS_DOC_STATUS_APPROVED)GlobalConstants.GDMS_DOC_STATUS_FINAL)GlobalConstants.GDMS_DOC_STATUS_EFFECTIVE))



SynchronizeRelatedDocumentContributions(SPWeb oWeb)

Retrieving allitems from the Document List, Converting to datatable if collection is not empty. creating query to making a call in database to all the list items
strQuery =

Removing all the items from "Document Contributions" List. using the for loop.
Looping through the each item of Document List, retrieving row to the datarow object and retrieving the
gdms_r_object_id and checking whether it has value or not, If it has
//now get GDMS document object based on object id
// get a string concating all related document ids
// constructing query to get related document info
// assume the list is empty,

Checking the condition of
GDMS_DOC_STATUS_FINAL
GDMS_DOC_STATUS_HA_APPROVED
GDMS_DOC_STATUS_APPROVED
GDMS_DOC_STATUS_EFFECTIVE and inseting the fields accordingly.
// foreach related document returned, create an entry in document contribution list
"select r_object_id, r_version_label,xm_status,title ,subtype, pfe_xm_p_lc_change,i_chronicle_id from gtc_document(all) where r_object_id in


Timer job logs has been logged on the
LIST_Logs, Logs list.


How to create TimerJob
1. Create a class inherited from SPJobDefinition create constructor and override the Execute method write your logic in Execute method.
  GDMSContributionSync : SPJobDefinition{
// No Argument Constructor (required for the system internal operation)
{
}

:
{
}
public
{}

2. Create the feature that should have a reciever class in which you configure the Job, where you add the job on the portal and configure it for schedule.

// GDMSDocumentSync Job

GDMSDocumentSync objTimerJob = new GDMSDocumentSync(GlobalConstants.FEATURE_GDMS_DOCUMENT_SYNC, currentSite.WebApplication);SPDailySchedule schedule = new SPDailySchedule();//this service will start at 1 AMschedule.BeginHour = 2;
schedule.BeginMinute = 2;
schedule.EndHour = 3;
objTimerJob.Schedule = schedule;
objTimerJob.Title =
currentSite.WebApplication.JobDefinitions.Add(objTimerJob);
objTimerJob.Update();

3. Activate a feature, If you can develope a screen to schedule the job to run.


objContSyncTimerJob.Title = jobName;
objContSyncTimerJob.Schedule = schedule;
objContSyncTimerJob.IsDisabled = rdbLstJobStatus.Items[1].Selected;
objContSyncTimerJob.Update();
case GlobalConstants.FEATURE_GDMS_CONTRIBUTION_SYNC:GDMSContributionSync objContSyncTimerJob = new GDMSContributionSync(GlobalConstants.FEATURE_GDMS_CONTRIBUTION_SYNC, currentSite.WebApplication);

4. You can debug the timer job from OWStimer process.
GlobalConstants.FEATURE_GDMS_DOCUMENT_SYNC;
override void Execute(Guid targetInstanceId)
public GDMSContributionSync()public GDMSContributionSync(string JobName, SPWebApplication objWebApplication)base(JobName, objWebApplication, null, SPJobLockType.Job)
class

Wednesday, May 2, 2012

Best Practice while developing shareoint solutions

Best Practices: Common Coding Issues When Using the SharePoint Object Model

Windows SharePoint Services 3
66 out of 98 rated this helpful - Rate this topic
Summary: Learn common issues encountered by developers who write custom code by using the SharePoint object model. (15 printed pages)
Scott Harris, Microsoft Corporation
Mike Ammerlaan, Microsoft Corporation
Steve Peschka, Microsoft Corporation
Roger Lamb, Microsoft Corporation
Published: September 2007
Updated: July 2010
Applies to: Windows SharePoint Services 3.0, Windows SharePoint Services 2.0, Microsoft Office SharePoint Server 2007
Contents

Overview

Developers who write custom code with the SharePoint object model will encounter common issues related to performance, extensibility, and scalability. This article is a resource for developers who are working to troubleshoot and improve the performance of existing SharePoint applications or who are writing new SharePoint applications. In both cases, it is important to understand how to make the SharePoint object model work efficiently, and how to apply general programming techniques (such as caching and threading) to the SharePoint platform specifically. This information can make it easier to design your applications correctly, find and fix problem areas in your code, and avoid known pitfalls of using the SharePoint object model.
The following areas reflect the most common general concerns encountered by SharePoint developers:
  • Using SharePoint data and objects efficiently
  • Performance concerns related to folders, lists, and SPQuery objects
  • Writing applications that scale to large numbers of users
  • Using Web controls and timer jobs
  • Disposing of SharePoint objects
This article addresses all but the last of these issues. For guidance on disposing of SharePoint objects, see Best Practices: Using Disposable Windows SharePoint Services Objects.
Additionally, we recommend that you read the following orientation topics as good starting points for using the SharePoint object model:

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.
This section describes these common areas of concern so that you can learn ways to optimize your use of SharePoint objects and data.

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.
Bb687949.note(en-us,office.12).gifNote:
The caching techniques discussed in this section are not the same as the custom caching options for Web content management that are discussed in Custom Caching Overview.

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.

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 void CacheData()
{
   SPListItemCollection oListItems;

   oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
   if(oListItems == null)
   {
      oListItems = DoQueryToReturnItems();
      Cache.Add("ListItemCacheName", oListItems, ..);
   }
}
Although the use of the cache in this example is functionally correct, because the ASP.NET cache object is thread safe, it introduces potential performance problems. (For more information about ASP.NET caching, see the Cache class.) If the query in the preceding example takes 10 seconds to complete, many users could try to access that page simultaneously during that amount of time. In this case, all of the users would run the same query, which would attempt to update the same cache object. If that same query runs 10, 50, or 100 times, with multiple threads trying to update the same object at the same time—especially on multiprocess, hyperthreaded computers—performance problems would become especially severe.
To prevent multiple queries from accessing the same objects simultaneously, you must change the code as follows.
Applying a Lock
Checking for null
private static object _lock =  new object();

public void CacheData()
{
   SPListItemCollection oListItems;

   lock(_lock) 
   {
      oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
      if(oListItems == null)
      {
         oListItems = DoQueryToReturnItems();
         Cache.Add("ListItemCacheName", oListItems, ..);
     }
   }
}
You can increase performance slightly by placing the lock inside the if(oListItems == null) code block. When you do this, you do not need to suspend all threads while checking to see if the data is already cached. Depending on the time it takes the query to return the data, it is still possible that more than one user might be running the query at the same time. This is especially true if you are running on multiprocessor computers. Remember that the more processors that are running and the longer the query takes to run, the more likely putting the lock in the if() code block will cause problems. If you want to make absolutely sure that another thread has not created oListItems before the current thread has a chance to work on it, you could use the following pattern.
Applying a Lock
Rechecking for null
private static object _lock =  new object();

public void CacheData()
{
   SPListItemCollection oListItems;
       oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
      if(oListItems == null)
      {
         lock (_lock) 
         {
              //Ensure that the data was not loaded by a concurrent thread while waiting for lock.
              oListItems = (SPListItemCollection)Cache[“ListItemCacheName”];
              if (oListItems == null)
              {
                   oListItems = DoQueryToReturnItems();
                   Cache.Add("ListItemCacheName", oListItems, ..);
              }
         }
     }
}

If the cache is already populated, this last example performs as well as the initial implementation. If the cache is not populated and the system is under a light load, acquiring the lock will cause a slight performance penalty. This approach should significantly improve performance when the system is under a heavy load, because the query will be executed only once instead of multiple times, and queries are usually expensive in comparison with the cost of synchronization.
The code in these examples suspends all other threads in a critical section running in IIS, and prevents other threads from accessing the cached object until it is completely built. This addresses the thread synchronization issue; however, the code is still not correct because it is caching an object that is not thread safe.
To address thread safety, you can cache a DataTable object that is created from the SPListItemCollection object. You would modify the previous example as follows so that your code gets the data from the DataTable object.
Good Coding Practice
Caching a DataTable Object
private static object _lock =  new object();

public void CacheData()
{
   DataTable oDataTable;
   SPListItemCollection oListItems;
   lock(_lock)
   {
           oDataTable = (DataTable)Cache["ListItemCacheName"];
           if(oDataTable == null)
           {
              oListItems = DoQueryToReturnItems();
              oDataTable = oListItems.GetDataTable();
              Cache.Add("ListItemCacheName", oDataTable, ..);
           }
   }
}
For more information and examples of using the DataTable object, and other good ideas for developing SharePoint applications, see the reference topic for the DataTable class.

Using Objects in Event Receivers

Do not instantiate SPWeb, SPSite, SPList, or SPListItem objects within an event receiver. Event receivers that instantiate SPSite, SPWeb, SPList, or SPListItem objects instead of using the instances passed via the event properties can cause the following problems:
  • 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.
Bad Coding Practice
Instantiating an SPSite Object Inside an Event Receiver
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.
        }
    }
}

Good Coding Practice
Using SPItemEventProperties
// 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.
If you do not apply this fix in your code, when you call Update on the new instance, you must invalidate it with the Invalidate method in the appropriate child class of SPEventPropertiesBase (for example, SPItemEventProperties.InvalidateListItem or SPItemEventProperties.InvalidateWeb).

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.

      Good Coding Practice

      Retrieving Items with SPList.GetItems

      SPQuery query = new SPQuery();
      SPListItemCollection spListItems ; 
      string lastItemIdOnPage = null; // Page position.
      int itemCount = 2000
       
      while (itemCount == 2000)
      {
          // Include only the fields you will use.
          query.ViewFields = "<FieldRef Name=\"ID\"/><FieldRef Name=\"ContentTypeId\"/>";   
          query.RowLimit = 2000; // Only select the top 2000.
          // Include items in subfolder (if necessary).
          query.ViewAttributes = "Scope=\"Recursive\"";
          StringBuilder sb = new StringBuilder();
          // To make it order by ID and stop scanning the table, specify the OrderBy override attribute.
          sb.Append("<OrderBy Override=\"TRUE\"><FieldRef Name=\"ID\"/></OrderBy>");
          //.. Append more text as necessary ..
          query.Query = sb.ToString();
          // Get 2,000 more items.
       
          SPListItemCollectionPosition pos = new SPListItemCollectionPosition(lastItemIdOnPage);
          query.ListItemCollectionPosition = pos; //page info
          spListItems = spList.GetItems(query);
          lastItemIdOnPage = spListItems.ListItemCollectionPosition.PagingInfo;
          // Code to enumerate the spListItems.
          // If itemCount <2000, we finish the enumeration.
          itemCount = spListItems.Count;
      
      }
      
      
      The following example shows how to enumerate and paginate a large list.

      SPWeb oWebsite = SPContext.Current.Web;
      SPList oList = oWebsite.Lists["Announcements"];
      
      SPQuery oQuery = new SPQuery();
      oQuery.RowLimit = 10;
      int intIndex = 1;
      
      do
      {
          Response.Write("<BR>Page: " + intIndex + "<BR>");
          SPListItemCollection collListItems = oList.GetItems(oQuery);
      
          foreach (SPListItem oListItem in collListItems)
          {
              Response.Write(SPEncode.HtmlEncode(oListItem["Title"].ToString()) +"<BR>");
          }
      
          oQuery.ListItemCollectionPosition = collListItems.ListItemCollectionPosition;
          intIndex++;
      } while (oQuery.ListItemCollectionPosition != null);
      
      
    • 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.

    Table 1. Alternatives to SPList.Items

    Poor Performing Methods and Properties Better Performing Alternatives
    SPList.Items.Count SPList.ItemCount
    SPList.Items.XmlDataSchema Create an SPQuery object to retrieve only the items you want.
    SPList.Items.NumberOfFields Create an SPQuery object (specifying the ViewFields) to retrieve only the items you want.
    SPList.Items[System.Guid] SPList.GetItemByUniqueId(System.Guid)
    SPList.Items[System.Int32] SPList.GetItemById(System.Int32)
    SPList.Items.GetItemById(System.Int32) SPList.GetItemById(System.Int32)
    SPList.Items.ReorderItems(System.Boolean[],System.Int32[],System.Int32) Perform a paged query by using SPQuery and reorder the items within each page.
    SPFolder.Files.Count SPFolder.ItemCount
    Bb687949.note(en-us,office.12).gifNote:
    The SPList.ItemCount property is the recommended way to retrieve the number of items in a list. As a side effect of tuning this property for performance, however, the property can occasionally return unexpected results. If the precise number is required, you should use the poorer performing GetItems(SPQuery query), as shown in the preceding code example.
  3. Use PortalSiteMapProvider (Microsoft Office SharePoint Server 2007 only).

    Steve Peschka's white paper Working with Large Lists in Office SharePoint Server 2007 describes an efficient approach to retrieving list data in Office SharePoint Server 2007 by using the PortalSiteMapProvider class. PortalSiteMapProvider provides an automatic caching infrastructure for retrieving list data. The GetCachedListItemsByQuery method of PortalSiteMapProvider takes an SPQuery object as a parameter, and then checks its cache to determine whether the items already exist. If they do, the method returns the cached results. If not, it queries the list and stores the results in a cache. This approach works especially well when you are retrieving list data that does not change significantly over time. When data sets change frequently, the class incurs the performance cost of continually writing to the cache in addition to the costs of reading from the database. Consider that the PortalSiteMapProvider class uses the site collection object cache to store data. This cache has a default size of 100 MB. You can increase the size of this cache for each site collection on the object cache settings page for the site collection. But this memory is taken from the shared memory available to the application pool and can therefore affect the performance of other applications. Another significant limitation is that you cannot use the PortalSiteMapProvider class in applications based on Windows Forms. The following code example shows how to use this method.

    Good Coding Practice

    Using PortalSiteMap Provider

    // Get the current SPWeb object. 
    SPWeb curWeb = SPControl.GetContextWeb(HttpContext.Current); 
    
    // Create the query. 
    SPQuery curQry = new SPQuery(); 
    curQry.Query = "<Where><Eq><FieldRef Name='Expense_x0020_Category'/>
    <Value Type='Text'>Hotel</Value></Eq></Where>"; 
    
    // Create an instance of PortalSiteMapProvider. 
    PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider; 
    PortalWebSiteMapNode pNode = ps.FindSiteMapNode(curWeb.ServerRelativeUrl) as PortalWebSiteMapNode; 
    
    // Retrieve the items. 
    
    SiteMapNodeCollection pItems = ps.GetCachedListItemsByQuery(pNode, "myListName_NotID", curQry, curWeb); 
    
    // Enumerate through all of the matches. 
    foreach (PortalListItemSiteMapNode pItem in pItems)
       { 
       // Do something with each match.
       }
    
    
  4. 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] and SPWeb.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.

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 each SPListItemVersion 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);  
}
}
If you are deleting versions of items in a document library, you can use a similar approach by retrieving the SPListItem.File.Versions property, as in the following code example.
Good Coding Practice
Deleting each version of a list item in a document library by using the SPFileVersionCollection.DeleteByID method
SPSite site = new SPSite("site url");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["custom list name"];
SPFile file = list.RootFolder.Files[0];
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);  
}
}

Writing Applications That Scale to Large Numbers of Users

You might not be aware that you need to write your code to be scalable so that it can handle multiple users simultaneously. A good example is creating custom navigation information for all sites and subsites on each page or as part of a master page. If you have a SharePoint site on a corporate intranet and each department has its own site with many subsites, your code might resemble the following.
public void GetNavigationInfoForAllSitesAndWebs()
{
   foreach(SPSite oSPSite in SPContext.Current.Site.WebApplication.Sites)
   {
      try
      {
         SPWeb oSPWeb  = oSPSite.RootWeb;
         AddAllWebs(oSPWeb );
      }
      finally
      {
         oSPSite.Dispose();
      }
   }
}
public void AddAllWebs(SPWeb oSPWeb)
{
   foreach(SPWeb oSubWeb in oSPWeb.Webs)
   {
       try
       {
           //.. Code to add items ..
           AddAllWebs(oSubWeb);
       }
       finally
       {
            if (oSubWeb != null)
            oSubWeb.Dispose();
       }
   }
}
While the previous code disposes of objects properly, it still causes problems because the code iterates through the same lists over and over. For example, if you have 10 site collections and an average of 20 sites or subsites per site collection, you would iterate through the same code 200 times. For a small number of users this might not cause bad performance. But, as you add more users to the system, the problem gets worse, as shown in Table 2.

Table 2. Iterations increase as number of users increases

Users Iterations
102000
5010000
100200000
250500000
Although the code executes for each user that hits the system, the data remains the same for each user. The impact of this can vary depending on what the code is doing. In some cases, repeating code might not cause a performance problem; however, in the previous example the system must create a COM object (SPSite or SPWeb objects are created when retrieved from their collections), retrieve data from the object, and then dispose of the object for each item in the collection. This can have a significant impact on performance.
How to make this code more scalable or fine-tune it for a multiple user environment can be a hard question to answer. It depends on what the application is designed to do.
You should take the following into consideration when asking how to make code more scalable:
  • Is the data static (seldom changes), somewhat static (changes occasionally), or dynamic (changes constantly)?
  • Is the data the same for all users, or does it change? For example, does it change depending on the user who is logged on, the part of the site being accessed, or the time of year (seasonal information)?
  • Is the data easily accessible or does it require a long time to return the data? For example, is it returning from a long-running database query or from remote databases that can have some network latency in the data transfers?
  • Is the data public or does it require a higher level of security?
  • What is the size of the data?
  • Is the SharePoint site on a single server or on a server farm?
How you answer the previous questions will determine in which of several ways you can make your code more scalable and handle multiple users. The intent of this article is not to provide answers for all of the questions or scenarios but to provide a few ideas that you can apply to your specific needs. The following sections offer areas for your consideration.

Caching Raw Data

You can cache your data by using the System.Web.Caching.Cache object. This object requires that you query the data one time and store it in the cache for access by other users.
If your data is static, you can set up the cache to load the data only one time and not expire until the application is restarted, or to load the data once per day to ensure data freshness. You can create the cache item when the application starts, when the first user session starts, or when the first user tries to access that data.
If your data is somewhat static, you can set up the cached items to expire within a certain number of seconds, minutes, or hours after the data is created. This enables you to refresh your data within a timeframe that is acceptable to your users. Even if the data is cached for only 30 seconds, under heavy loads you will still see improved performance because you are running the code only one time every 30 seconds instead of multiple times per second for each user who hits the system.
Security trimming is another issue to consider whenever you cache data. For example, if you cache items as you iterate through a list, you may get only a subset of the data (the data that the current user can see), or if you use a DataTable object to cache all of the items in a list, you have no easy way of applying security trimming to users who belong to groups that can see only a subset of the data. For more information about storing security trimmed data in caches, see the CrossListQueryCache class.
In addition, ensure you consider the issues described earlier in Caching Data and Objects.

Building Data Before Displaying It

Think about how your cached data will be used. If this data is used to make run-time decisions, putting it into a DataSet or DataTable object might be the best way to store it. You can then query those objects for the data to make run-time decisions. If the data is being used to display a list, table, or formatted page to the user, consider building a display object and storing that object in the cache. At run time, you need only retrieve the object from the cache and call its render function to display its contents. You could also store the rendered output; however, this can lead to security issues and the cached item could be quite large, causing increased page swapping or memory fragmentation.

Caching For a Single Server or Server Farm

Depending on how you set up your SharePoint site, you might have to address certain caching issues differently. If your data must be the same on all servers at all times, then you must ensure that the same data is cached on each server.
One way to ensure this is to create the cached data and store it on a common server or in a Microsoft SQL Server database. Again, you must consider how much time it takes to access the data and what security issues can arise from storing the data on a common server.
You can also create business-layer objects that cache data on a common sever, and then access that data by using various interprocess communications that are available in networking objects or APIs.

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 thick CreateChildControls 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 CreateChildControls method 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.
For an example, see Walkthrough: Creating a Custom Field Type. In addition, see the Microsoft.SharePoint.WebControls namespace.

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.

Conclusion

To ensure that your SharePoint system performs at its best, you need to be able to answer the following questions about the code you write:
  • Does my code properly dispose of SharePoint objects?
  • Does my code cache objects properly?
  • Does my code cache the correct types of objects?
  • Does my code use thread synchronization when necessary?
  • Does my code work as efficiently for 1,000 users as it does for 10 users?
If you consider these issues when you write your code, your SharePoint system will run more efficiently and your users will have a much better experience. You can also help to prevent unexpected failures and errors in your system.

Acknowledgements

We would like to acknowledge the following persons for their tremendous help in technical reviews for this article: James Waymire (Microsoft Corporation), Duray Akar (Microsoft Corporation), Rashid Aga (Microsoft Corporation), Roger Lamb (Microsoft Corporation), and Jeff Lin (Microsoft Corporation).

Additional Resources


  1. Don't cache SharePoint objects that are not Thread Safe
Let's take real time scenario, we have to bind dropdown list with the SharePoint list. We know SharePoint list which we are binding with dropdown list is not going to change frequently, so caching will be better option to improve the performance of the application. Sample code is mentioned below:
                      SPListItemCollection colItems;
            if(null != HttpRuntime.Cache[key])
            {
                ddlItems = (SPListItemCollection)HttpRuntime.Cache[key];
            }
            else
            {
                // Do query on sharepoint listand cach SPListItemCollection object
            }
But we are unaware that SPListItemCollection object contains an embedded SPWeb object that is not thread safe and should not be cached.

Good Coding Practice is to cache DataTable in place of SPListItemCollection object.
Sample Code:
         private static object _lock =  new object();

         private DataTable GetDropDownItems()
         {
         DataTable dtDropDownItems;

   SPListItemCollection objListItems;
   lock(_lock)
   {
             dtDropDownItems= (DataTable)Cache["CachedDropDownItems"];
           if(dtDropDownItems== null)
           {
              objListItems = //Do query onSharePoint List
              dtDropDownItems= objListItems.GetDataTable();
              Cache.Add("CachedDropDownItems ", dtDropDownItems,..); // provide rest of the parameter of this method
           }
   }
   }

Note: There are various methods to cache object like HttpRuntime, System.Web.Caching.Cache,  and HttpContext.Current.Cache. Choose one to the method to cache depending upon your application requirement.

    2. Retrieve or fetch SPList instance from SPWeb object: There might be the multiple approach to get the instance of SPList in SharePoint. But while developing an application we should keep in mind about performance of the application. Mentioned below are two approach to achieve the same.

        Approach 1: Not Recommended
        SPList objSpList = <SPWeb>.Lists["<List Title>"];  

        Approach 2: Recommended
        SPList objSpList = <SPWeb>.GetList("<List URL>");
   
        In the first approach, SharePoint loads "metadata" of all the SharePoint lists of current SPWeb object and then create SPList instance by Title comparison and also if Title of SharePoint list gets changed, There will be a code change. But in the second approach, SharePoint fetches GUID of the SharePoint list by list url and then loads the "metadata" of that particular list. User can not update the list URL after SharePoint list creation. So there is no possibility of any code change in this approach.

    3. JavaScript methods call on page load in SharePoint: Sometime we need to call JavaScript methods on page to change UI or to set some controls value. we can use window.onload event to achieve this functionality. But I personally recommend that to use "_spBodyOnLoadFunctionNames" method provided by SharePoint because sometimes window.onload don't work properly.
        Approach 1: Not Recommended
        window.onload = funcation(){//JavaScript code};
        window.onload = <JavaScript method name>;

        Approach 2: Recommended
        _spBodyOnLoadFunctionNames.push('<JavaScript method name>');

     4. Set RowLimit, ViewFields, and ViewFiledsOnly properties while fetching data from SharePoint list:
         Let take me take an example to make understand importance of these properties.
      Scenario: Suppose there isa list to store employee details. Following fields are present in this list:
<!--[if !supportLists]-->·    Name
<!--[if !supportLists]-->·    Designation
<!--[if !supportLists]-->·    Domain
<!--[if !supportLists]-->·    Address
<!--[if !supportLists]-->·    Email
<!--[if !supportLists]-->·    Contact Number
<!--[if !supportLists]-->·    Rating
      We have to create a webpart to show top 5 employees name, designation and email in the home page of site based on employee rating.

Monday, April 30, 2012

Web Parts

WebPart Life Cycle
OnInit: This method handles initialization of the control.
OnLoad: This event handles the Load event. This is also used for initialize the control but is not intended for loading data or other processing functionality.
CreateChildControls: This is the most popular event in web part life cycle. This creates any child controls. So if you are adding any control to display then you have to write in this method.
EnsureChildControls: This method ensures that CreateChildControls has executed. EnsureChildControls method must be called to prevent null reference exceptions.
SaveViewState: View state of the web part saved.
OnPreRender: This method handles or initiates tasks such as data loading that must complete before the control can render.
Page.PreRenderComplete: The page fires the PreRenderComplete event after all controls have completed their OnPreRender methods.
Render: This method is used to render everything.
RenderContents: Renders the contents of the control only, inside of the outer tags and style properties.
OnUnload: Performs the final cleanup.

Visual Web Part Limitations

Starting in Visual Studio, you can add visual web parts to sandboxed SharePoint solutions and farm solutions. However, visual web parts have the following limitations:
  • Visual web parts don't support replaceable parameters. For more information, see Replaceable Parameters.
  • User controls or visual web parts can't be dragged and dropped or copied onto visual web parts. This action causes a build error.
  • Visual web parts don't directly support SharePoint server tokens such as $SPUrl. For more information, see "Token Restrictions in Sandboxed Visual Web Parts" in the topic Troubleshooting SharePoint Solutions.
  • Visual web parts in a sandboxed solution occasionally get the error, "The sandboxed code execution request was refused because the Sandboxed Code Host Service was too busy to handle the request." For more information about this error, see this post in the SharePoint Developer Team Blog.
  • Server-side JavaScript debugging isn't supported in Visual Studio, but client-side JavaScript debugging is supported.
    Although you can add inline JavaScript to a server-side markup file, debugging isn't supported for breakpoints added to the markup. To debug JavaScript, reference an external JavaScript file in the markup file, and then set the breakpoints in the JavaScript file.
  • Debugging of inline ASP.NET code must be done in the generated code file instead of in the markup file.
  • Visual web parts don't support the use of the <@ Assembly Src= directive.
  • SharePoint web controls and some ASP.NET controls aren't supported in the SharePoint sandboxed environment. If unsupported controls are used on a visual web part in a sandboxed solution, the error, "The type or namespace name 'Theme' does not exist in the namespace 'Microsoft.SharePoint.WebControls'" appears.
 
 
Good Example:
 
 
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Data;

namespace SharepointTraingSolution.BasicWebPart
{
    [ToolboxItemAttribute(false)]
    public class BasicWebPart : WebPart
    {
        private DataGrid grid;
        private static string verbText = "Show Managers Only";
        private Label errorMessage = new Label();
        protected string xmlFilePath;

        [Personalizable(PersonalizationScope.Shared), WebBrowsable(true),
         WebDisplayName("Path to Employee Data File"),
         WebDescription("Location of the XML file that contains employee data")]
        public string DataFilePath
        {
            get
            {
                return xmlFilePath;
            }
            set
            {
                xmlFilePath = value;
            }
        }
        public override WebPartVerbCollection Verbs
        {
            get
            {
                WebPartVerb customVerb = new WebPartVerb("Manager_Filter_Verb",
                    new WebPartEventHandler(CustomVerbEventHandler));
                customVerb.Text = verbText;
                customVerb.Description = "Shows only employees that are managers";
                WebPartVerb[] newVerbs = new WebPartVerb[] { customVerb };
                return new WebPartVerbCollection(base.Verbs, newVerbs);
            }
        }
        protected void CustomVerbEventHandler(object sender, WebPartEventArgs args)
        {
            int titleColumn = 2;
            foreach (DataGridItem item in grid.Items)
            {
                if (item.Cells[titleColumn].Text != "Manager")
                {
                    if (item.Visible == true)
                    {
                        item.Visible = false;
                    }
                    else
                    {
                        item.Visible = true;
                    }
                }
            }
            if (verbText == "Show Managers Only")
            {
                verbText = "Show All Employees";
            }
            else
            {
                verbText = "Show Managers Only";
            }
        }
       
        protected override void CreateChildControls()
        {
            // Define the grid control that displays employee data in the Web Part.
            grid = new DataGrid();
            grid.Width = Unit.Percentage(100);
            grid.GridLines = GridLines.Horizontal;
            grid.HeaderStyle.CssClass = "ms-vh2";
            grid.CellPadding = 2;
            grid.BorderWidth = Unit.Pixel(5);
            grid.HeaderStyle.Font.Bold = true;
            grid.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
            // Populate the grid control with data in the employee data file.
            try
            {
                DataSet dataset = new DataSet();
                dataset.ReadXml(xmlFilePath, XmlReadMode.InferSchema);
                grid.DataSource = dataset;
                grid.DataBind();
            }
            catch (Exception x)
            {
                errorMessage.Text += x.Message;
            }
            // Add control to the controls collection of the Web Part.
            Controls.Add(grid);
            Controls.Add(errorMessage);
            base.CreateChildControls();
        }
      
       
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);
            writer.Write("<HTML><HEAD><BODY><TABLE BORDER=1><TR><TD>RAJ SHARMA</TD></TR><TD>RAJ SHARMA</TD></TR><TD>RAJ SHARMA</TD></TR></TABLE></BODY></HEAD></HTML>");
        }
    }
}
 
<?xml version="1.0" encoding="utf-8" ?>
    <employees xmlns="http://schemas.microsoft.com/vsto/samples">
       <employee>
           <name>David Hamilton</name>
           <hireDate>2001-05-11</hireDate>
           <title>Sales Associate</title>
       </employee>
       <employee>
           <name>Karina Leal</name>
           <hireDate>1999-04-01</hireDate>
           <title>Manager</title>
       </employee>
       <employee>
           <name>Nancy Davolio</name>
           <hireDate>1992-05-01</hireDate>
           <title>Sales Associate</title>
       </employee>
       <employee>
           <name>Steven Buchanan</name>
           <hireDate>1955-03-04</hireDate>
           <title>Manager</title>
       </employee>
       <employee>
           <name>Suyama Michael</name>
           <hireDate>1963-07-02</hireDate>
           <title>Sales Associate</title>
       </employee>
    </employees>


Understanding SharePoint Delegate Control

8 December, 2010 (15:25) | SharePoint 2010 - Object Model | By: G Vijai Kumar
In this article I’m going to explain about delegate control, before we jump start into the technical talk we will understand first what is the meaning of Delegates
As I believe most of us we know that in general delegates are also called as ambassadors, diplomats, representatives etc.
A delegate having high ranks has most importance for example ranks like 1, 2, 3. Rank1 delegate officer has most significant role than rank2 delegate officer.
There can be so many delegate officers or ambassadors serving for Country X for example: A delegate officer may look after the relations between Country X and Country A, another delegate ambassador may look after the relations between Country X and Country B, even some times the delegate officers have to visit to the Country A or Country B depending upon the call.
Now we will speak real technical vocabulary of delegates, SharePoint has a couple of delegate controls like
AdditionalPageHead
GlobalSiteLink0
GlobalSiteLink1
GlobalSiteLink2
PublishingConsole
QuickLaunchDataSource
SmallSearchInputBox
TopNavigationDataSource
Apart from the above controls, we can also create our own custom delegate controls
The XML schema for delegate control is below:
1
2
3
<?xml version="1.0" encoding="utf-8" ?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
 <Control Id="SmallSearchInputBox" Sequence="100" Url="/templates/mysearchcontrol.ascx"/>
</Elements>
In the above schema you can view the properties for the delegate control as Control Id, Sequence and URL. We identify the delegate controls based on Control Id, Sequence number. The Sequence number defines the rank of the delegate, URL describes the source location of the control.
As we discussed already above that “Delegates having high ranks has most importance” in the same way delegate control who’s Sequence id is less has most significant role in SharePoint site and will render on the site as first preference.
Also we have discussed that “some times the delegate officers have to visit to the Country A or Country B depending upon the call” in the same way if we have custom delegate control deployed on site and activated, the least Sequence control will load on site depending upon the user action.
What is the use of delegate control?
Using the delegate control a developer can customize the SharePoint site controls without editing or even touching the master page.
Note: We are not customizing the existing (default) delegate control but we are creating our own control loading onto the SharePoint site.
Let’s suppose assume one scenario, if we want to customize the SharePoint search box (by default SharePoint 2010 site has got input search box with one textbox and one button beside) see figure 1
Figure 1 - SharePoint 2010 Default Search Box
Figure 1 - SharePoint 2010 Default Search Box
Now I will try to customize the default search box, the requirement is to display the search box with scope drop down list, and also customizing the search button image with a arrow image button.
First open Visual Studio 2010 and click New > Project see figure 2
Figure 2 - Creating New Visual Studio 2010 Project
Figure 2 - Creating New Visual Studio 2010 Project
After project got created, I have deleted the not in use file (you can keep it there won’t be any problem if you don’t delete) because of maintaing clean solution I have removed user control, webpart related files see figure 3
Figure 3 - Solution Explorer File Structure
Figure 3 - Solution Explorer File Structure
Then add the following code in Elements.xml file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
  <!--<Module Name="VisualWebPart1" List="113" Url="_catalogs/wp">
    <File Path="VisualWebPart1\VisualWebPart1.webpart" Url="CustomDelegateControl_VisualWebPart1.webpart" Type="GhostableInLibrary" >
      <Property Name="Group" Value="Custom" />
    </File>
  </Module>-->
  <Control
     Id="SmallSearchInputBox"
     Sequence="23"
     ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx"
     ControlAssembly="Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
    <Property Name="QueryPromptString">This control is customized.....</Property>
    <Property Name="SearchBoxTableClass">search-box</Property>
    <Property Name="GoImageUrl">/_layouts/images/goviewfiles.png</Property>
    <Property Name="GoImageUrlRTL">/_layouts/images/goviewfiles.png</Property>
    <Property Name="GoImageActiveUrl">/_layouts/images/goviewfiles.png</Property>
    <Property Name="GoImageActiveUrlRTL">/_layouts/images/goviewfiles.png</Property>
    <Property Name="UseSiteDefaults">true</Property>
    <Property Name="FrameType">None</Property>
  </Control>
</Elements>
In the Element.xml file I have commented the Module section see figure 4
Figure 4 - Custom Delegate Control Element.xml file
Figure 4 - Custom Delegate Control Element.xml file
Now we are almost done, try to build, deploy and activate the feature which will result in change of SharePoint default search box with your customized control on fly without modifying the master page see figure 5
Figure 5 - SharePoint 2010 Custom Search Input Box
Figure 5 - SharePoint 2010 Custom Search Input Box
At run time, this control accepts the union of control elements declared at the server farm, Web application, site collection, and Web site levels. The control that has the lowest sequence number is added to the control tree by means of the DelegateControl. In the case of a sequence tie, the order of controls is arbitrary.
The sequence number of the DelegateControl can be used to integrate a portal search control in SharePoint Foundation. The default search control has a sequence number of 100, and a portal search, for example, could be activated at the site collection level with a sequence number of 50. In this way, SharePoint Foundation replaces the default search control with the portal search control in all places where the search control is invoked.

A delegate control is not inherently designable because it is ignorant of the actual control that gets instantiated inside it. The best it can do is render the design-time HTML of the chosen control for the particular instance. At best, the designer provides an option to "hardcode" the control, meaning replace the SharePoint:DelegateControl with the current control that is being returned via the Features infrastructure. The developer can then customize the control.

How to: Customize a Delegate Control

This example shows the basic process of creating and implementing a delegate control. The delegate control resides in the AdditionalPageHead control on the page. It registers some ECMAScript (JavaScript, JScript) on the page.

To build the delegate control

  1. Start SharePoint development tools in Microsoft Visual Studio 2010.
  2. On the File menu, point to New, and then click Project.
  3. In Project Types, under Visual Basic or C#, select Empty SharePoint Project.
  4. Type EcmaScriptDelegate as the project name. Click OK.
  5. In the SharePoint Customization Wizard, choose Deploy as a farm solution. Click Finish.
  6. In the Solution Explorer, right-click the EcmaScriptDelegate project. Select Add and then New Item.
  7. In the Add New Item dialog box, click the Code group and choose the Class template. Type EcmaScriptDelegateControl as the Name and then click Add.
  8. Next, you must add a reference to System.Web. In the Solution Explorer, right-click the References folder and select Add Reference. In the Add Reference dialog, click the .NET tab and find System.Web in the list. Click OK.
  9. In the EcmaScriptDelegateControl file that is displayed, add the following using statement.
    using System.Web.UI.WebControls;
    
  10. Change the base class of EcmaScriptDelegateControl to WebControl by modifying the following line.
    class EcmaScriptDelegateControl : WebControl
    
  11. Override the OnLoad method by adding the following code.
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);
    }
    
    
  12. Inside the OnLoad method, add the following code to put JavaScript on the page.
      string helloAlert = "alert('Hello, world!');";
      this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "popup", helloAlert, true);
    
    
Now, you have built the delegate control for the project. Next, you will create the Feature to deploy the control.

To create a Feature to deploy the control

  1. In the Solution Explorer, right-click the EcmaScriptDelegate project and select Add and then New Item.
  2. In the Add New Item dialog box, choose the Empty Element template and type EcmaScriptDelegateFeature as the Name. Click Add.
  3. Insert the following XML inside the Elements element. The Id attribute identifies the delegate where the control is rendered. The ControlAssembly and ControlClass attributes are unique to your control. For more information about how to find the full assembly name, see How to: Create a Tool to Get the Full Name of an Assembly.
    <Control Id="AdditionalPageHead" ControlAssembly="EcmaScriptDelegate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=public key token" ControlClass="EcmaScriptDelegate.EcmaScriptDelegateControl">
    
    
You now have both the control and the Feature you need to deploy the control. Controls require a SafeControl entry in the web.config file in order to run on the page. The following procedure adds a SafeControl entry for your control.

To add a SafeControl entry

  1. In the Solution Explorer, click EcmaScriptDelegateFeature and click ... in the Safe Control Entries property.
  2. Click Add in the Safe Control Entries dialog.
  3. In the Properties box, ensure that the Namespace property is the correct value. This is the namespace of your control. Also, ensure that the Safe property is set to true. Click OK.
Now that the SafeControl entry is added, you can deploy the solution.

To deploy and test the delegate control

  1. Press F5 to run the solution.
  2. When the page loads, a dialog box appears that says Hello, world!. This is the script that the delegate control has added to the page.

 

Web Parts in SharePoint Foundation

Web Parts are server-side controls that run inside the context of site pages in Microsoft SharePoint Foundation. There are many Web Parts available by default, and you can also build your own custom Web Parts in SharePoint Foundation. They are editable and configurable by users. Web Parts let users add functionality to a site page by simply putting them on the page. SharePoint Foundation includes many default Web Parts. In addition, you can build your own Web Parts.

Types of webparts


There are two types of webparts available the first is Asp.net webparts and other is sharepoint web. the Asp.net inherited from system.web.UI.webcontrols.webparts and sharepoint webpart inherited from system.sharepoint.webparts.webpart. it uses Microsoft.SharePoint.dll and ASP.net uses System.Web.dll.

Asp.net webparts can be used to both enviroment .net as well as sharepoint. while sharepoint webparts can be used in sharepoint enviroment.

Custom Web parts

The term customization implies that changes are seen by all site members. Individual users can further personalize Web Parts page by adding, reconfiguring, and removing Web Parts. The term personalization implies that these changes are seen only by the user who made them. A site owner or a site member who has the appropriate permissions can customize Web Parts page by using a browser or by using Microsoft SharePoint Designer to add, reconfigure, or remove a Web Part.

Custom web parts used to provided the following facitlities..


Connectable Web Parts

Connectable web parts is the special type of webparts which provides the connection between two or more web parts, connectable web parts exchange the information to each other, there are some kind of prents child relationship. they provides the interface to consume and consumer interface to exchange the information.

Adding a web part property
after adding hte web part add a new property which is used to personalize the web part to the indiviudual user. It apears in the tools to edi


  • Create custom properties that you can display and modify in the user interface.
  • Improve performance and scalability. A compiled custom Web Part runs faster than a script.
  • Implement proprietary code without disclosing the source code.
  • Secure and control access to content within the Web Part. Built-in Web Parts enable any users who have the appropriate permissions to change content and alter Web Part functionality. With a custom Web Part, you can determine the content or properties to display to users, regardless of their permissions.
  • Make your Web Part connectable, allowing Web Parts to provide or access data from other connectable Web Parts.
  • Interact with object models that are exposed in SharePoint Foundation. For example, you can create a custom Web Part to save documents to a SharePoint Foundation document library.
  • Control the Web Part cache by using built-in cache tools. For example, you can use these tools to specify when to read, write, or invalidate the Web Part cache.
  • Benefit from a rich development environment with debugging features that are provided by tools such as Microsoft Visual Studio 2010.
  • Create a base class for other Web Parts to extend. For example, to create a collection of Web Parts that have similar features and functionality, create a custom base class from which multiple Web Parts can inherit. This reduces the overall cost of developing and testing subsequent Web Parts.
  • Control Web Part implementation. For example, you can write a custom server-side Web Part that connects to a back-end database, or you can create a Web Part that is compatible with a broader range of Web browsers.

Web Parts

1. To render web part Basically.. you pass the parmater in the override render method(System.web.ui.htmltextwriter writer)
then writer.write--used to render any static text
writer.renderbegintag--used to render < 
writer.renderendtag--used to render >
writer.write("<td><tr>") you can render whole html as well..

2. To render any control in your web part you basically override a create child method
    declare button
 Button btnAdd
btnAdd= new Button()
add properties on btnAdd if you want
this.controls.Add(btnAdd)--- to add button control in your form

To add event handler on the button
btnAdd.Click += new eventhandler(btnAdd_Click);

method would be genrated like this private void btnAdd_Click(object sender,eventargs e)

3. If you want manually rendering of your controls the override void render method and inside do the below code
this.EnsureChildControls();
btnAdd.RenderControls(writer);
do the br or whatever you want

4. Adding a new property and get that value into your code on web part.
[WebBrowsable(true),Category("Miscellaneous"),Personalizable(PersonalizationScope.Shared),WebDisplayName("Enter some text")]
public string CustomTextProp{get;set;}
 on the prerender
lbl_MySelection.Text = this.webpat.CustomTextProp.ToString();

5. Customize the content by query webpart
add a publishing dll in your reference
add using microsoft.Sharepoint.Publishing.Webcontrols
and inherit the class
public class ExtendCustomQueryWebPart : ContentByQueryWebPart

6. Loading User control :
create variable of control type and on the createdchildcontrols method write the below code
base.createchildcontrols();
this.controls.clear()
control = this.page.loadControl(@"/_controltemplates/usercontrol/simplecontrol.ascx");
this.controls.add(control);



Web Part Life Cycle
the life-cycle of a webpart is like this:
- OnInit
- OnLoad
- Applies personalization
- Web Part connections
- CreateChildControls
- OnPreRender
- SaveViewState
- Render

if it's a postback this is  the sequence, a bit different
- OnInit
- LoadViewState
- CreateChildControls
- OnLoad
- Applies personalization
- Postback events
- Web Part connections
- OnPreRender
- SaveViewState
- Render