Tuesday, June 25, 2013

BeforeProperties and AfterProperties in Sharepoint Event Receivers

Many of us have used BeforeProperties and AfterProperties while working with Event Receiver, but we don't know how and when to use these properties while accessing the data/field value.

These are facts we need to consider while working with Event receiver.

1) We should not use Before properties for accessing change of value at List level.
2) Before properties are available only with Document Library


I am summarizing about BeforeProperties, AfterProperties and properties.ListItem in sharepoint event receiver context.

List:
ListBeforePropertiesAfterPropertiesproperties.ListItem
ItemAddingNo valueNew valueNull
ItemAddedNo valueNew valueNew value
ItemUpdatingNo valueChanged valueOriginal value
ItemUpdatedNo valueChanged valueChanged value
ItemDeletingNo valueNo valueOriginal value
ItemDeletedNo valueNo valueNull

Library:

LibraryBeforePropertiesAfterPropertiesproperties.ListItem
ItemAddingNo valueNo valueNull
ItemAddedNo valueNo valueNew value
ItemUpdatingOriginal valueChanged valueOriginal value
ItemUpdatedOriginal valueChanged valueChanged value
ItemDeletingNo valueNo valueOriginal value
ItemDeletedNo valueNo valueNull


Here one more scenario we need to consider before we conclude this topic.

I have one example where I need to prevent the user from entering the same value for a column.

Ex: Suppose column called Description and its initial value is "Test" and user go to the list and update the item for that column with the same value we need to prevent this. How to achieve this?

So if we observe carefully with above table then we have answer available immediately.
In the ItemUpdating Event we can check the condition like

if(properties.ListItem["Description"] != properties.AfterProperties["Description"])
{
         //Cancel the event
         properties.Cancel = true;
         properties.ErrorMessage = "The column is having same original value";
}


 

Wednesday, June 5, 2013

How to check SharePoint Version

If you are a SharePoint resource and some time you may come across any web site which looks similar to MOSS/ SharePoint 2010/2013 but you are not sure whether its a SharePoint site or not(may be they will revamp completely with CSS, master page so that no one can identify its SharePoint site or not). In that case how to check its SharePoint site or not.

Follow below steps which will show which version of SharePoint or is the site itself is not SharePoint one.

1) Open the site in IE(any of the site)

2) Click F12 which will open IE developer tool.

3) Click on Network tab






4) Click on start Capturing button
 





5) Refresh the page so that it will capture the traffic.

6) Now click on any of the URL under traffic as shown below.
ex: /_layouts/15/init.js?rev

 
7) Click on "Go to detailed View"

8) Click on Response headers and check the MicrosoftSharePointTeamServices header :

For MOSS it will show as 12.0.0.
SharePoint 2010 14.0.0.
SharePoint 2013 it will be 15.0.0

 

Wednesday, May 29, 2013

Sharepoint 2010 Querying Sharepoint Data

There are many ways we can query sharepoint data. Below are the objects used for querying sharepoint data.

1) SPQuery - This is used to retrieve data from a specific list.

2) SPSiteDataQuery - This is used to query data from multiple lists across different sites in a site collection.

3) CrossListQueryCache - The SharePoint CrossListQueryCache class provides a highly scalable way to run site wide queries.  It provides all the power of SPSiteDataQuery without the performance implications.  However it has some major gotchas that you should be aware of before using.

4) PortalSiteMapProvider - The PortalSiteMapProvider class allows us to access cached objects for sites, lists, and list items.

Details and Examples:

SPQuery:

Scenario:

To get the list of items from SharePoint list whose age is greater than 10.
Assumption: Student List is created with FirstName, LastName, Age and the name of the list is Student.

Code:

SPWeb spWeb = SPContext.Current.Site.RootWeb;
SPList spList = spWeb.Lists["Students"];
SPQuery spQuery = new SPQuery();
spQuery.Query = "Write Caml query here"  //like  select * from table where Age > 10

//Execution of below line of code will return SPListItemCollection

SPListItemCollection collListItems = spList.GetItems(spQuery);
 
//Loop through each item and perform the operation

foreach (SPListItem spListItem in collListItems) {
         //Process each item
}

There will be an question arise why can't we use Linq instead of SPQuery.

If we have Linq then it needs to run under full trust proxy which is not possible in sand box solution at that time we need to use SPQuery.


SPSiteDataQuery:

Scenario:

To get list of items from different list under multiple sites(webs) under same site collection.

Follow these steps for using the SPSiteDataQuery class
-          Create a SPSiteDataQuery instance.
-          Set properties on the SPSiteDataQuery instance to specify the lists or list types to include in the query, the individual sites to include in the query, and the CAML query itself.
-          Call the GetSiteData method on a SPWeb instance, passing in the SPSiteDataQuery instance as a parameter. The GetSiteData method returns a DataTable.

Code:

       SPSiteDataQuery dataQuery = new SPSiteDataQuery();
      //Here if we set Scope to Recursive then the query considers the current Web site and  all subsites of the current Web site.

     //If we set Scope to SiteCollection, the query considers all Web sites that are in the same site collection as the current Web site.
    //Code snippet will be like dataQuery.Webs = "";
      dataQuery.Webs = "";
      dataQuery.Lists = "";
      dataQuery.ViewFields = "";
      dataQuery.Query =  "12345
"; 
      DataTable dtable = web.GetSiteData(dataQuery);
      //Do whatever the required operations here
 
When to use SPSiteDataQuery:
 
SPSiteDataQuery is commonly used in list aggregation scenarios, where list data from team sites or other subsites is collated and presented in a single interface. The SPSiteDataQuery will only aggregate data from SharePoint lists and will ignore data from external lists.
In terms of efficiency, the SPSiteDataQuery class provides an optimal approach to data access in the following scenarios:
-          When we need to query multiple lists within the same site collection for the same content
-          When we need to query across two or more lists that are not related by lookup columns
The SPSiteDataQuery class is optimized for querying list data across multiple sites in a site collection and across multiple lists within a single site.

CrossListQueryCache:

The SharePoint CrossListQueryCache class provides a highly scalable way to run site wide queries.
The CrossListQueryInfo object uses the CrossListQueryInfo object to get the cached results or, if there are no cached results available, it performs a cross-list query to the database and then caches the results for future use.

How to use CrossListQueryCache:
 CrossListQueryInfo query = new CrossListQueryInfo();
 query.Lists = "";
  query.Query = "" +
                          "Completed";
   query.ViewFields = "";
      query.UseCache = true;
 CrossListQueryCache cache = new CrossListQueryCache(query);
 DataTable results = cache.GetSiteData(spSite);

Where to use CrossListQueryCache:

It should be used when we need to query one or more lists and store the results in cache so subsequent calls are at near lightning speed.
There are 4 overloads for CrossListQueryCache.GetSiteData.  Two of the overloads cache the results and two do not.

CrossListQueryCache RoutineUses Cache
GetSiteData (SPSite)Yes
GetSiteData (SPWeb)No
GetSiteData (SPSite, String)Yes
GetSiteData (SPWeb, SPSiteDataQuery)No
 
So unless we are using one of the overloads that support caching and have the CrossListQueryInfo.UseCache property set to true we might as well use SPSiteDataQuery.
 
PortalSiteMapProvider:

The PortalSiteMapProvider class allows us to access cached objects for sites, lists, and list items. It also provides methods for executing SPQuery and SPSiteDataQuery queries against cached SharePoint lists. We can use the GetCachedListItemsByQuery method to cache the query results. Executing a SPSiteDataQuery query with a PortalSiteMapProvider object is similar to using the CrossListQueryCache class.

How to use PortalSiteMapProvider:

To retrieve items from a list PortalSiteMapProvider class includes a method called GetCachedListItemsByQuery that retrieves data from a list based on a SPQuery object that is provided as a parameter to the method call.
The method then looks in its cache to see if the items already exist. If they do, the method returns the cached results, and if not, it queries the list, stores the results in cache and returns them from the method call.

Code:

SPQuery spQuery = new SPQuery();
spQuery.Query = ”” +
Completed
”;PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider;
var pNode = ps.FindSiteMapNode(web.ServerRelativeUrl) as PortalWebSiteMapNode;

var Items = ps.GetCachedListItemsByQuery(pNode, ”Tasks”, spQuery, web);
foreach (var item in Items )
{
//Do what ever want here
}

Where to use PortalSiteMapProvider:

A primary advantage of the PortalMapSiteProvider class is its use and management of the SharePoint object cache. The object cache provides highly efficient access to objects that are not part of a list. By default, the PortalSiteMapProvider class queries and manages the object cache.

Thursday, May 16, 2013

Sharepoint 2010 Timer Jobs

In this article I am going to show how to make our timer job to run in the specified servers in the farm which is having Front end server or App server.

If we don't specify server then timer jobs will run in any of the front/app servers.

We have a requirement where we need to run our timer job only in app server since our timer job was making an web service call. You may think what's the wrong running timer job in front end server. Here ports(where we are making call to web service) were opened only in app servers not in FE servers.

Suppose if the timer job picks from front server then definitely it will throw exception in order to avoid this situation we change the logic to run only in app servers as shown below, before that I will give an overview of sharepoint timer jobs.

Sharepoint timer jobs should inherit from the SPJobDefinition class. This class provides 3 constructors for us:

SPJobDefinition()Default constructor needed for serialization purposes. Initializes a new instance of the SPJobDefinition class.
SPJobDefinition(String, SPWebApplication, SPServer, SPJobLockType) Instantiates a timer job associated with the given SPWebApplication. Initializes a new instance of the SPJobDefinition class and provides parameters for specifying key objects.
SPJobDefinition(String, SPService, SPServer, SPJobLockType) Instantiates a timer job associated with the given SPService. Initializes a new instance of the SPJobDefinition class and provides parameters for specifying key objects.

First constructor is required in any of the custom timer job and we can use either 2nd or 3rd constructor in our code but either one of them is mandatory(Job definitions must be associated with a service or Web application)

Sample code:

public class Sharepoint2010TimerJob : SPJobDefinition
{
     public Sharepoint2010TimerJob(): base()
     {
     }

     public Sharepoint2010TimerJob(string name, SPService service, SPServer server,      SPJobLockType lockType) : base(name, service, server, lockType)
     {
     }

     public Sharepoint2010TimerJob(string name, SPWebApplication webApplication, SPServer server,      SPJobLockType lockType) : base(name, webApplication, server, lockType)
     {
     }

     public override void Execute(Guid targetInstanceId)
     {     
             //Execute Timer Job Tasks
            //This is the place where we are making our web service call and doing executing the logic
     }
}

Below is our normal sharepoint job definition code now I will show how to make our timer service to run in the specified server.

Open the feature receiver class for our timer job.

     [Guid("{39ad45db-49a6-45d2-ae99-4cd677ecf65d}")]
     public class Sharepoint2010TimerFeatureReceiver :      SPFeatureReceiver
     {
    
              string timerJobName = "SharePoint 2010 Timer job";
    
              public override void FeatureActivated(SPFeatureReceiverProperties properties)
             {
                       SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
                
                      //Delete the job if it is already existing in our case this is not required we can comment the below line.
                      DeleteJob(webApp.JobDefinitions, timerJobName);

                     //Declare the SPServer object
                     SPServer serverToRunOn = null;

                    //Get all the servers in the farm
                    SPServerCollection servers = SPFarm.Local.Servers;

                   //Checking for property bag entry if it is already there then assign the value
                    if (webApp.Properties[timerJobName + "_Server"] != null)
                   {
                              serverToRunOn = servers[webApp.Properties[timerJobName + "_Server"].ToString()];
                    }

                 //Here we can check if form is configured with single server
                  if (serverToRunOn == null)
                  {
                           foreach (SPServer server in servers)
                           {
                                   if (server.Role == SPServerRole.SingleServer)
                                  {
                                           serverToRunOn = server;
                                           break;
                                   }
                            }
                    }
              
                   // if you want to run timer service in app server then below is the code we need to use
                   if (serverToRunOn == null)
                  {
                           foreach (SPServer server in servers)
                          {
                                   if (server.Role == SPServerRole.Application)
                                  {
                                             serverToRunOn = server;
                                             break;
                                  }   
                          }
                  }

                  // If we want to run the code in front end server then use the below piece of code.
                  if (serverToRunOn == null)
                 {
                          foreach (SPServer server in servers)     
                         {
                                if (server.Role == SPServerRole.WebFrontEnd)
                               {
                                         serverToRunOn = server;
                                         break;
                               }
                        }
                 }

               //In the above piece of code I am checking so many conditions and may be every one will think why so many conditions are required if I need to assign for only app server.

             //Here is my answer lets assume we need to deploy the code in dev server where its running in single server then 1st condition will be useful

            //If we move the code to staging environment which is running with multiple server but no dedicated app server then we require 3rd condition
    
           //If we move the code to ppe(pre production environment) which is replica of Prod then it will have proper sharepoint set up like 2 front end, 1 app server , 1 db server(small farm) then 2nd condtion will execute.

          //This is what we are looking to run the timer job to run in app server.
        
          // Define the schedule
          Sharepoint2010TimerJob timerJob = new Sharepoint2010TimerJob(timerJobName, webApp, serverToRunOn, SPJobLockType.Job);

          webApp.Properties[timerJobName + "_Server"] = serverToRunOn.Name;

          //Schedule as per the requirement
          SPMinuteSchedule minuteSchedule = new SPMinuteSchedule();
          minuteSchedule.BeginSecond = 1;
          minuteSchedule.EndSecond = 59;
          minuteSchedule.Interval = 10;
          timerJob.Schedule = minuteSchedule;
          // Update the schedule      timerJob.Update();
       }
  }
}

Wednesday, April 24, 2013

Sharepoint : LINQ Examples

In this post I am going to show some of the LINQ to SharePoint examples which will be useful in performing CRUD operations.

Before that lets think about SQL, CAML and LINQ

In SharePoint all the data will be stored in SQL databases. SharePoint List will be an front end for doing CRUD operation. Since the users does not have DB access List will be used as an interface to perform CRUD operation.

Suppose if we want to get few records from SharePoint list based on some condition then we need to write CAML query to get the records.

Writing CAML query is little bit tedious even though we have excellent CAML Query builder. To overcome this problem we have LINQ for SharePoint which will internally run CAML to perform CRUD operations.

So LINQ is a front end for CAML, internally CAML is front end to SQL.

Here I am showing how to use LINQ to SharePoint using SPMetal.exe

Lets create a SharePoint List called EmployeeDetails with following fields.

EmployeeID - Integer FirstName - Single Line Text LastName - Single Line Text DOB - Date field Phone - Number Email - Single Line Text

Create some dummy records in the employee list.

Requirement:

Lets assume we have one timer job which will send an EMail to the employee whose birthday is today :).

1) Open SPMetal.exe from CommondPrompt

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN



Run the following command from window.

c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN>SPMETAL.exe /web:http://sharepoint2010 /namespace:SharePointConsoleApplication1 /code:ListEntities.cs (This will create the entity class with the namespace.



or

c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN>SPMETAL.exe /web:http://sharepoint2010 /code:ListEntities.cs (This will create Entity class without namespace)



Add ListEntities.cs file from 14 hive folder to the project and verify the namespace(make sure Microsoft.Sharepoint.Linq dll reference has been added in the project)

The structure of the Project should be as below after adding the entity class into the project.



Read Operation:

I have pasted below code which will display Employee Name whose birthday is today. (Its like an Select statement in SQL)

using System;
using System.Linq;
using Microsoft.SharePoint;
namespace SharePointConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//Open the List Entities Data context file and pass the Site url as parameter
using (ListEntitiesDataContext list = new ListEntitiesDataContext("http://sharepoint2010"))
{
//Once data context is ready its simple Linq statement to fetch the records based on the condition
var spItems = from a in list.EmployeeDetails where a.DOB == System.DateTime.Now select a;
//Loop through all the items
foreach (var item in spItems)
{
//Here we can write our business logic just displaying the employess first name
Console.WriteLine(item.FirstName);
}
}
}
}
}

Will continue :)

Friday, April 19, 2013

List of Sharepoint 2010 Developer Tools

Below are some of the Tools/application which will be handy during development/debugging phase of the projects.

1) WSP builder
http://wspbuilder.codeplex.com/releases/view/30858
The WSP builder will create .wsp file extension for the sharepoint, event though Visual Studio provide OOB package builder still this tool will be handy.

2) Caml
http://www.u2u.be/res/Tools/files/CamlBuilderSetupv4.0.0.0.zip Using this tool we can easily build complex query to fetch data from SharePoint list.

3) TFS power tool
http://visualstudiogallery.msdn.microsoft.com/c255a1e4-04ba-4f68-8f4e-cd473d6b971f It's a plugin for Visual Studio and provides great flexibility to work with TFS.

4) Powershell
http://www.powergui.org/downloads.jspa Provides GUI for writing Powershell scripts to perform all sharepoint related administrative/developer task.

5) SPManger
http://spm.codeplex.com/releases/view/51438 The SharePoint Manager is UI based SharePoint object model explorer.

6) UlsViewer
http://archive.msdn.microsoft.com/ULSViewer This tool provides the sharepoint ULS log information where we can search or filtering the data based on category etc.

7) IE/Firefox developer tool bar
Out of the box tool where we can do style changes or debugging javascript code.

8) SPMetal
http://linqtosharepoint.codeplex.com/wikipage?title=SPMetal

9) CCleaner
http://download.cnet.com/CCleaner/3000-18512_4-10315544.html To clear cookies/browser history and this will be helpful when we use cookies related operation for storing data.

10) ILSpy
http://sourceforge.net/projects/sharpdevelop/files/ILSpy/2.0/ILSpy_Master_2.1.0.1603_RTW_Binaries.zip/download
This tool allows to decompile and browse the content of any .NET assembly

11) Fiddler
http://fiddler2.com/
Fiddler is a free web debugging tool which logs all HTTP(S) traffic between your computer and the Internet

12) CKS Visual Studio Extension
SPServer
http://visualstudiogallery.msdn.microsoft.com/en-us/ee876627-962c-4c35-a4a6-a4d89bfb61dc
Foundation
http://visualstudiogallery.msdn.microsoft.com/a346880f-2d29-47a6-84a2-f2d568dd6997/
This tool extends the Visual Studio 2010 SharePoint project system with advanced templates

13) Sharepoint Installer
http://autospinstaller.codeplex.com/downloads/get/100843

14) SPDisposecheck
http://archive.msdn.microsoft.com/SPDisposeCheck
SPDisposeCheck is a tool that helps developers and administrators check custom SharePoint solutions that use the SharePoint Object Model helping measure against known Microsoft dispose best practices

Thursday, April 18, 2013

Sharepoint Delegate control - Notification bar in sharepoint

In this post I am going to show how to add a notification bar in the sharepoint site(Notification bar is used to display notification to the users about the site maintenance activity)
Step 1: Override the delegate control in the master page
Step 2: Associate this delegate control as sharepoint feature(This will be usefull for the site admin, whenever its required they will be activate and deactivate this feature)
Open Visual Studio and create new project called NotificationFeature
Add new sharepoint Feature Called NotificationFeature and set the scope to Site level.
Add new user control called NotificationControl(Map to sharepoint control template folder at the 14 hive)
Open NotificationControl.ascx file and add the below code to display notification bar.
Here I have added jQuery reference and javascript function which set the div background color and div tag to display the message. (Adding jQuery reference and validate method is optional we can set the background color for the div tag directly)
Add New Empty element to the project and name it as NotificationControl.
Open Element.xml file and add below code.
<Control Id="AdditionalPageHead" ControlSrc="~/_CONTROLTEMPLATES/NotificationFeature/NotificationControl.ascx" Sequence="15100" /> Finally our Element.xml file looks like below.

Add jQuery file to the layouts folder. This step is optional since I am applying style for the div element through jQuery I am using this else we can skip this step.
Final structure of our project:
Build, Package and deploy the solution. And activate the Notification Feature at the site level.
Now our notification bar will be displayed when the user open the site.