Wednesday 20 February 2013

Best approaches -Object model in SharePoint 2010


If you are using SharePoint Object model then there are certain things to remember that are related to performance, extensibility, and scalability.

Approach-1:

While writing code it should ensure that any unmanaged resources should be released as soon as they are no longer needed. Though garbage collector automatically releases memory allocated to unused objects, but it will release in a unpredictable manner. The .NET Framework provides the IDisposable interface, which exposes a Dispose method that you should call to explicitly release these unmanaged resources. To invoke Disnpose method, you can use the using keyword, you can use the try/finally code block or you can explicitly invoke Dispose method. Example of using keyword:

using (SPSite site = new SPSite("URL of the Site Collection"))
{
// Code here
}

Internally the compiler converts the using block to try/finally block as shown below.
SPSite site = null;
try
{
site = new SPSite("URL of the Site Collection");
// Code here
}
finally
{
if (site != null)
site.Dispose();
}

The SPSite and SPWeb types both implement the IDisposable interface, and both allocate unmanaged memory. If you do not correctly release SPSite and SPWeb instances, you will probably experience memory leaks, crashes, and frequent application pool recycles.
But if they are derived from the context object then the framework will take care of releasing resources, you should not release the resources.
·         SPContext.Current.Web
·         SPContext.Current.Site
·         SPContext.Current.Site.RootWeb

For example SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb().
Here the web object is derived from the SPContext, so we should not dispose that. Here SPWeb object web.Dispose() automatically called. Read this tutorial Disposing SharePoint Objects

Approach-2:

SPDisposeCheck is a tool that analyzes the custom SharePoint solution that uses SharePoint object model. If you can using SPSite or SPWeb objects then it is very much necessary to dispose the objects. Many SharePoint API's allocate COM based memory that is not released by CLR garbage collection and must be released by calling the Dispose() methods. As the name suggests SPDisposeCheck will check your assemblies and will let you know the memory leaks according to the Microsoft standards. It is a command line utility and called by the Visual studio addin. It takes path to a managed .DLL or .EXE or the path to a directory containing many managed assemblies. Then it starts analyzing the memory leaks.

You can download the from the below URL
http://code.msdn.microsoft.com/SPDisposeCheck
After downloading this and during installation you can tick on the check boxes to integrate SPDisposeCheck to visual studio 2010.
Once the Integration happens it can be found under Tools -> SharePoint Dispose Check in Visual Studio. Read this tutorial for more on SPDisposeCheck for SharePoint 2010

Approach-3:

SPQuery: If you are using SPQuery object to retrieve data from a large list then you should give a RowLimit else it perform poorly and will fail on large lists. So give RowLimit between 1 and 2000.
Also you should limit the result set in threshold in Microsoft SharePoint Foundation 2010, which is by default 5000 items.

Approach-4:

While deploying code using wsp solutions, ensure code is not in debug mode when compiled, it runs slower and potentially can crash/holdup your production environment.
Approach-5:

Use the new SharePoint 2010 feature Developer Dashboard for viewing SharePoint page performance.

Approach-6:

If you are working with event receiver then Do not instantiate an SPWeb, SPSite, SPList, or SPListItem object within an event receiver. Because it creates sometimes Significant additional roundtrips to the database and Calls to the Update method on these instances can cause subsequent Update calls in other registered event receivers to fails.
For example follow like below:
So instead of writing like
using (SPSite site = new SPSite(properties.WebUrl))
use like below:
SPWeb web = properties.OpenWeb();
SPListItem item = properties.ListItem;

Ensure these things during development…!

Tuesday 12 February 2013

Feature Stapling in SharePoint 2010


Feature Stapling allows you to create a feature and then associate it with any site definition without ever touching the site definition files themselves. Your feature will be activated when the site is provisioned.

To staple a Feature to a site definition, you actually need to create another Feature that will do the stapling, and this feature is called as Stapler Feature. A feature which is going to be stapled/associated with a site definition is called as Staplee Feature.

Consider a situation like you've created an awesome master page(already deployed) for your team sites but you are a bit annoyed that you have to manually set every new site to use this master page after they are created.so using Feature stapling we are going to set a default master page at the time of creating a new site itself.
  • Create new Empty SharePoint Project.
  • Right Click Feature and click Add Feature.Now you will see Feature.Temlate.Xml.(Staplee Feature)
  • Right click on created Feature1 and Click add Event Receiver.
                      

  • You will Find a Event Receiver class file where you can code your own logic.
  • We can now edit the feature receiver code to make it set our custom master page when the feature is activated. This is done in the FeatureActivated method. Our end result should look something like this:
  • public override void FeatureActivated(SPFeatureReceiverProperties properties) { try { using (SPWeb currentWeb = properties.Feature.Parent as SPWeb) { using (SPSite currentSite = currentWeb.Site) { string masterPageUrl = string.Format("{0}/_catalogs/masterpage/CustomTeamSite.master", currentSite.ServerRelativeUrl).Replace("//", "/"); currentWeb.CustomMasterUrl = masterPageUrl; currentWeb.MasterUrl = masterPageUrl; currentWeb.Update(); } } } catch (Exception ex) { string errorMessage = string.Format("An exception occured while trying to activate the feature. Message: '{0}'.", ex.Message); throw new SPException(errorMessage); } }
  • We probably want our feature to clean up after itself when it's activated, so we'll go ahead and add some code to the FeatureDeactivating method that sets the site's master page back to 'default.master'. The code looks something like this:
public override void FeatureDeactivating(SPFeatureReceiverProperties properies)
{ try { using (SPWeb currentWeb = properties.Feature.Parent as SPWeb) { using (SPSite currentSite = currentWeb.Site) { string masterPageUrl = string.Format("{0}/_catalogs/masterpage/default.master", currentSite.ServerRelativeUrl).Replace("//", "/"); currentWeb.CustomMasterUrl = masterPageUrl; currentWeb.MasterUrl = masterPageUrl; currentWeb.Update(); } } } catch (Exception ex) { string errorMessage = string.Format("An exception occured while trying to deactivate the feature. Message: '{0}'.", ex.Message); throw new SPException(errorMessage); } }
  • Staplee Feature work is over the next step is to create Stapler Feature.
  • So we have to create our Stapler (Feature2) which will associate Feature1 with the site definition.
  • The scope of Feature2 should be Farm Level.
                                  

  • Add new Empy Element "Elements" to the project.
  • We will need the GUID from Feature1 . You can find this in the manifest(yellow mark in the below image).

  • Edit Element.xml file in the newly added element and add follwing line,
<?xml version="1.0" encoding="utf-8"?>
<FeatureSiteTemplateAssociation TemplateName="GLOBAL" Id="493a82e4-f05b-4244-91df-c99ba69db085"></FeatureSiteTemplateAssociation>
<FeatureSiteTemplateAssociation TemplateName="STS#1" Id="493a82e4-f05b-4244-91df-c99ba69db085"></FeatureSiteTemplateAssociation>
</Elements>
  • To activate the feature for type of sites in web application, we need to associate stapling a feature to global site definition(TemplateName="GLOBAL") and blank site (TemplateName="STS#1").
  •  Deploy the project.
   9. Now whenever you create a new site using site definition specified   
      in FeatureSiteTemplateAssociation (ie...the TemplateName) staplee 
      feature will automatically get activated.

Friday 8 February 2013

Debug a Feature Receiver in VS 2010


To debug a feature receiver in Visual Studio 2010:

1. Open the Visual Studio 2010 project that contains your feature.

2. In Solution Explorer, right-click the project node, and then click Properties.

3. On the SharePoint tab, in the Active Deployment Configuration drop-down list, click No Activation.

4. Then attach to the w3wp.exe process that is running your particular SharePoint instance.(However, I  have found that if you need to debug a feature that is activated with stsadm.exe, there is an extra step required.  The reason is that you need to not only attach to the w3wp.exe process but you also need to attach to stsadm.exe as well.).

5. Open the feature receiver class that you want to debug, and then insert a breakpoint. Hit F5 and enjoy!!

6.There is, however a very fast and easy way to start debugging your Feature EventReceiver’s overridden methods, like FeatureActivated() and FeaureDeactivating(): Simply add the following line of code at the point you want to start debugging:

1
System.Diagnostics.Debugger.Launch();



Thursday 7 February 2013

Debugging Event Receivers in SharePoint 2010


By default event receivers are asynchronous meaning that they run under the SharePoint timer service (OWSTIMER.exe). This means that the event receivers:
  1. Are not executed immediately, rather it is scheduled to be executed by OWSTIMER.exe.
  2. Don’t run under w3wp.exe process anymore, so when you want to debug your event receivers, you have to attach to OWSTIMER.EXE and wait till they are executed.
However, you can control this behavior using the Synchronization attribute:


If you set it to Synchronous, then the event receivers run immediately and under the w3wp.exe process. So, if your solution depends on event receivers highly and expect the results immediately, then you have to set it to Synchronous, else setting it to Asynchronous should do the job.
______________________________________________________________________________

Also, if you’re looking for a easy to debug an event receiver without having to manually attach a debugger to your code, you can use the System.Diagnostics.Debugger.Launch() method. 


1
System.Diagnostics.Debugger.Launch();



Add it anywhere you want  in your code, deploy your solution and begin testing. Before you can begin debugging, a popup window will appear providing you options where to debug your code, choose an option and begin to debug your code.

Debugging Custom SharePoint Timer Jobs

When you create a timer job for SharePoint 2010, you cannot directly press F5 to debug your code. Instead, you must attach the debugger to the SharePoint 2010 Timer process (Owstimer.exe). This how-to topic describes how to debug a timer job by attaching the Visual Studio debugger to the timer process.

Steps to debug a timer job in Visual Studio 2010
  1. On the Start menu, point to Administrative Tools, and then click Services.
  2. In the Services window, make sure the SharePoint 2010 Timer service is started(You can also restart this service to make the changes reflect in sharepoint server).
  3. In your Visual Studio 2010 project that contains your custom timer job,set the break point at the first line of Execute() method.
  4. Note Make sure that the code has not changed since you deployed the timer job; otherwise, the debugger will not match your source code to the deployed assembly.
  5. On the Debug menu, click Attach to Process.
  6. In the Attach to Process dialog box, click OWSTIMER.EXE, and then click Attach.
  7. In the SharePoint Central Administration Web site, click Monitoring, and then click Review job definitions.
  8. Click the name of your job, and then click Run Now on the Edit Timer Job page.
  9. Verify that the Visual Studio 2010 debugger stops execution on your breakpoint.
  10. Happy Debugging.
If the above steps didn't work properly then try the below steps,
  • Insert an always-failing assertion statement at the beginning of the Execute method. You should use Debug.Assert(false) rather than Trace.Assert(false) since debug calls are detached from the release builds; then you don’t have to remove them from your code before moving to staging or production.

  • Every time the timer job starts, you will get a pop-up window like the one shown in Figure 12. This window hinders the execution of the timer job until you close the message box. Note that timer jobs run in parallel, so this window will never halt the execution of other timer jobs running simultaneously. For now, leave this window alone.
  • You might be wondering why you should insert the assert statement at the beginning of the Execute method of the timer job. It is true that you can just attach a debugger to owstimer.exe and wait for the subsequent cycle of the timer job, but it could be tough to find out whether the application has been effectively attached to the process since the jobs may not fire for several minutes. You could be left with Visual Studio attached to the owstimer.exe process with breakpoints set and wondering whether the job is running or wondering whether the breakpoints are not being hit because of some problem with loading the symbol files(.pdb).By adding the following code to the Execute method, you will see your timer jobs running.
  • Any time you update your custom timer job class and deploy the assembly to the global assembly cache, you must restart all the timer services in the farm. If you don’t restart the timer service, it will run the old copy of your timer job class. Yes, the timer service caches the assemblies. Restarting the SharePoint timer service is the only way to refresh the assembly cache and force it to use your updated assembly. 
  • And follow the same steps again as mentioned above.
  • Happy Debugging.

Create a Custom Timer Job in SharePoint 2010

A Timer Job is a periodically executed task inside SharePoint Server like sending emails or deleting the list items etc... in timely manner.

DLL or Namespace reference required in the scheduled in the class

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

Steps To create a custom timer job:
  1. Open Visual Studio 2010 and select File –> New –> Project
  2. In the New Project window, under Installed Templates, select SharePoint –> 2010 and select Empty SharePoint Project. Give the project a Name and click OK.
  3. Enter the URL for SharePoint local site, check the Deploy as a farm solution, and click Finish.
  4. Create a new class.Right click on the project in the Solution Explorer window and select Add –> New Item.
  5. In the Add New Item window, under Installed Templates, select Visual C# –> Code and select Class.  Give the class a name as "ListTimerJob" and click OK.
  6. The new class needs to inherit from the Microsoft.SharePoint.Administration.SPJobDefinition class. 
    • Add a default constructor to the class that inherits from the default constructor of the base class. This is required for the serialization and de-serialization of your timer job.
    • Add a constructor that accepts an argument of type string(jobname) and a type SPWebApplication, as shown in the following code. This enables the base SPJobDefinition class to instantiate your timer job within a specific Web application.
    • The SPJobDefinition base constructor provides alternative overloads that you can use if you want to scope your timer job to an SPService instance instead of a Web application. 
    • And finally Within the ListTimerJob class, override the Execute method. The method should accept an argument of type Guid. In this case, the GUID represents the target Web application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;

namespace SPTimerJobExample
{
    public class ListTimerJob : SPJobDefinition
    {
    }
    //Optional
    public ListTimerJob(string jobName, SPService service, SPServer server, SPJobLockType targetType): base(jobName, service, server, targetType)
     {
      // if you want to scope your timer job to an SPService instance instead of a Web                                                     application,then you can use this constructor.
     }//
    public ListTimerJob(string jobName, SPWebApplication webApplication)
            : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
    {
            this.Title = "List Timer Job";
    }
    public override void Execute(Guid contentDbId)
    {
            SPSite site = new SPSite("http://spdemo2010:2012/");
            SPWeb web = site.OpenWeb();
            SPList list = web.Lists["TeamChat"];
            SPListItemCollection listItems = list.Items;
            for (int i = listItems.Count-1; i >= 0; i--)
                {
                    listItems[i].Delete();
                }
            web.Dispose();
            site.Dispose();
    }
}

7. Add a Feature to the solution by right clicking on Features in the Solution Explorer window and                   selecting Add Feature.So now Feature 1 will be created.
8. Right click on Feature1 and select Add Event Receiver.
9. A new event receiver class is created that handles the feature’s events.Copy and paste the following code, which handles the FeatureActivated event, installing the custom timer job, and handles the FeatureDeactivating event, uninstalling the custom timer job.


namespace UpshotSP.Features.Feature1
{
   [Guid("9a724fdb-e423-4232-9626-0cffc53fb74b")]

public class Feature1EventReceiver : SPFeatureReceiver
    {
        const string List_JOB_NAME = "List Timer Job";
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            // make sure the job isn't already registered
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
                if (job.Name == List_JOB_NAME )
                    job.Delete();
            }
            // install the job
            ListTimerJob listLoggerJob = new ListTimerJob(List_JOB_NAME , site.WebApplication);
            SPDailySchedule schedule = new SPDailySchedule();
            schedule.BeginHour = 2;
            schedule.BeginMinute = 10;
            schedule.BeginSecond = 0;
            schedule.EndHour = 2;
            schedule.EndMinute = 20;
            schedule.EndSecond = 0;
            listLoggerJob.Schedule = schedule;
            listLoggerJob.Update();
        }
        // method below to handle the event raised before a feature is deactivated.
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            // delete the job
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
                if (job.Name == List_JOB_NAME)
                    job.Delete();
            }
        }
    }
}


10. Select the appropriate scope where the new feature will be activated.  Double click Feature1.Feature in the Solution Explorer window and choose the desired Scope from the dropdown menu.
11. Deploy the solution by right clicking on the project in the Solution Explorer window and selecting Deploy.
12. Navigate to the SharePoint “TestList” list and verify that a new item has been added with the current day/time as the title and you see your custom timer job named "List Timer Job" under Manage Timer jobs in Central Admin.
Note: You can see all Timer Jobs from Central Administration > Monitoring > Manager Timer Jobs.
SPSchedule class is used to schedule the Timer Job in a timely manner,You can also use other schedule class as mentioned below,
  • Minute
  • Hour
  • Day
  • Week
  • Month
Ex:
            SPMinuteSchedule schedule = new SPMinuteSchedule();
            schedule.BeginSecond = 0;
            schedule.EndSecond = 59;
            schedule.Interval = 5;
            job.Schedule = schedule; 
            job.Update();
_____________________________________________________________________________

A better way to delete list item if you have a lot of items is to use a default query and specify a row limit of 100.
Also to delete fast and efficiently, use a delete batch command CAML script.

StringBuilder sbDelete = new StringBuilder("<Batch>");
for (int x = listItems.Count-1; x >= 0; x--)
{

 sbDelete.Append("<Method>") ;
            sbDelete.Append("<SetList Scope='Request'>" & listItems[x].ID.ToString & "</SetList>"); 
            sbDelete.Append("<SetVar Name='Cmd'>DELETE</SetVar>"); 
            sbDelete.Append("<SetVar Name='ID'>listItems[x].ID</SetVar>"); 
            sbDelete.Append("</Method>"); 
}
sbDelete.Append("</Batch>");
web.AllowUnsafeUpdates = True;
web.ProcessBatchData(sbDelete.ToString());