Thursday 30 May 2013

Debugging and Testing in SharePoint 2010

Debugging and Testing in SharePoint 2010

Debugging and Testing in SharePoint 2010 If we are developing any applications in SharePoint the first point after the start of development that comes into mind is
How can we debugg or test the application
How can we get the detailed error
I am covering most of the avialable ways and tools to answer the debugging and testing questions.

Enable custom errors

The starting point for any developer is enable the cutom errors so that we can get detailed error instead of
routine error message ‘an unexpected error has occured’
Go to the location C:\inetpub\wwwroot\wss\VirtualDirectories\80 the default sharepoint site virtual directory.
Open the web.config file in any editor like notepad and search for the following xml

CallStack and PageLevelTrace

Change the CallStack and AllowPageLevelTrace attribute values to true
Before:
<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">
After:
<SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="true">

CustomErrors node

Set the mode to off in CustomerErrors node
Before:
<customErrors mode="On" />
After:
<customErrors mode="Off" />

LAYOUTS folder CustomErrors node

Most of the time with the above changes we should see detailed error.
If not got to LAYOUTS folder at
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS
Modify the web.config file in it and set the mode to off in CustomeErrors node
Before:
<customErrors mode="On" />
After:
<customErrors mode="Off" />

Developer dashboard

SharePoint 2010 has powerfull tool called developer dashboard useful in debugging especially in a production environment.
With this tool we can see the stack trace of the current execution and also the SQL queries currently executing.
To enable the developer dashboard execute the following stsadm command:
stsadm -o setproperty -pn developer-dashboard -pv OnDemand
If we want to use powershell instead of stsadm, use the following script
$contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$dashboardSetting = $contentService.DeveloperDashboardSettings
$dashboardSetting.DisplayLevel = [Microsoft.SharePoint.Administration.SPDeveloperDashboardLevel]::On
$dashboardSetting.Update()
Ok, some of us always like the superhero c#. For them use the following code
SPWebService cntService = SPWebService.ContentService;
cntService.DeveloperDashboardSettings.DisplayLevel = SPDeveloperDashboardLevel.On;
cntService.DeveloperDashboardSettings.Update();
After executing this command, refresh your site and you can see a new icon on the top after the username.
If we click it and we can see the developer dashboard at the bottom of the same page. We can view the stack trace and many more. Click the icon again to close
the detailed screen

Attach debugger

The most commong task done by any .net or sharepoint developer is attaching a debugger.
In the dev environment where code is avialable we can attach to w3wp.exe process of the valid application. Sometimes, if we are not sure, attach all the process.
Sometimes the breakpoints do not load even after attaching the debugger. To resolve this issue click the Select button in the ‘Attach to Process’ screen and select only the Managed (v2.0,v1.1,v1.0) option.
If we want to debugg a sandboxed solution in Visual Studio, we have to attach SPUCWorkerProcess.exe process

Watch the logs

Checking the SharePoint logs will give proper information on the error. But, most of the time we end up not observing that due to huge file.
We have one good tool ULSViewer to observe the logs. Download it from msdn http://code.msdn.microsoft.com/ULSViewer and observe the log file comforatably

Miscelaneous Tools for Testing and Debugging

SPDisposeCheck

Microsoft has good tool called SPDisposeCheck, which will scan the code and tell us where we are not releasing the memory because of not calling the Dispose() method.
This tool saves us a lot of time in tracking down memory leaks. We can download SPDisposeCheck from http://code.msdn.microsoft.com/SPDisposeCheck.


IE developer tool

Interner Explorer devloper tool that comes with IE is very good tool to track down client side issues. Just press f12 button after opening the site from IE.
It has some good feauteres inspite of displaying css tree, it shows the performance of the script code, including the number of times a function was used and the amount of time it took.


Firebug

This is addon tool for FireFox. It is same as IE developer tool


Visual Round Trip Analyzer

The Visual Round Trip Analyzer (VRTA) sits on top of the network monitor tool from Microsoft and is a free add-on.
It provides a graphic representation of how long it takes a client to talk to a server
We can download VRTA from www.microsoft.com/downloads/details.aspx?FamilyID=119f3477-dced-41e3-a0e7-d8b5cae893a3&displaylang=en


Fiddler

Fiddler(www.fiddlertool.com) is a web debugging proxy that logs all HTTP traffic between client and server.
Fiddler allows us to inspect all HTTP traffic, set breakpoints, and view our incoming and outgoing data


Visual Studio Testing tools

Not but the least, Visual Studio 2010 has got some awsome tools for unit testing, code coverage, impact analysis, coded UI testing, web performance testing, and load testing.
Ofcourse, how to use them is out of scope of this post. But, I will try in near future as they have really some cool features.


Conclusion

Hope this article provided some good information regarding debugging and testing the applications in SharePoint 2010. Let me

Upload Excel data into SharePiont Custom List using Interop

Upload Excel data into SharePiont Custom List using Interop

In this post we will see how to upload excel data (using office.interop.excel) into SharePoint 2007 / SharePoint 2010 Custom List from object model(c#)
You can also check the article how to upload excel data using oledb provider

Upload excel data

The following code has method LoadExcelData() which reads data from ‘contacts.xls’ and inserts into SharePoint Custom List ‘ContactList’.
According to the schema of the ‘ContactList’ that I have created, the method ‘InsertIntoList’ in the following code has relevant code.
You can modify according to the schema of your Custom List and Excel file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Data;
using System.Data.OleDb;
using Microsoft.SharePoint;
  
namespace TestSharepointProject
{
    public class UploadExcelData
    {
        public void LoadExcelData()
        {
            string filePath = "@"C:\AdisGroup\Contacts\contacts.xls";
            //if you are using file upload control in sharepoint get the full path as follows assuming fileUpload1 is control instance
            //string filePath = fileUpload1.PostedFile.FileName
  
             if (!(string.IsNullOrEmpty(fileName)))
            {
                DataTable excelData = GetExcelDataTable(filePath);
                if (excelData != null)
                {
                    InsertIntoList(excelData,"ContactList");
                }
            }
        }
  
        private DataTable GetExcelDataTable(string filePath)
        {
            DataTable dt = new DataTable();
            Microsoft.Office.Interop.Excel.Application ExcelObj = new Microsoft.Office.Interop.Excel.Application();
            ExcelObj.DisplayAlerts = false;
            if (ExcelObj == null)
            {
                return null;
            }
            string filead = filePath;
            Microsoft.Office.Interop.Excel.Workbook theWorkbook = ExcelObj.Workbooks.Open(filead, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "",
            true, false, 0, true, false, false);
  
            Microsoft.Office.Interop.Excel.Sheets sheets = theWorkbook.Worksheets;
            Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(1);
            int index = 0;
            object rowIndex = 2;
  
            dt.Columns.Add("FirstName");
            dt.Columns.Add("LastName");
            dt.Columns.Add("FullName");
            dt.Columns.Add("LoginID");
            dt.Columns.Add("EmailAddress");
            dt.Columns.Add("PhoneNumberBusiness");
            dt.Columns.Add("Company");
  
            DataRow row;
            while (((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 1]).Value2 != null)
            {
                rowIndex = 2 + index;
                row = dt.NewRow();
                row[0] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 1]).Value2);
                row[1] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 2]).Value2);
                row[2] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 3]).Value2);
                row[3] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 4]).Value2);
                row[4] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 5]).Value2);
                row[5] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 6]).Value2);
                row[6] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 7]).Value2);
  
                index++;
                dt.Rows.Add(row);
            }
            ExcelObj.Workbooks.Close();
            return dt;
  
        }
  
         private void InsertIntoList(DataTable listTable, string contactListName)
        {
  
            SPWeb mySite = null;
            try
            {
  
                mySite = SPContext.Current.Web; //create web object if context is null
                mySite.AllowUnsafeUpdates = true;
                SPList contactList = mySite.Lists[contactListName];
                for (int iRow = 0; iRow < listTable.Rows.Count; iRow++)
                {
                    SPListItem newContact = contactList.Items.Add();
                    newContact["FirstName"] = Convert.ToString(listTable.Rows[iRow][0]);
                    newContact["LastName"] = Convert.ToString(listTable.Rows[iRow][1]);
                    newContact["FullName"] = Convert.ToString(listTable.Rows[iRow][2]);
                    newContact["LoginID"] = Convert.ToString(listTable.Rows[iRow][3]);
                    newContact["EmailAddress"] = Convert.ToString(listTable.Rows[iRow][4]);
                    newContact["PhoneNumber"] = Convert.ToString(listTable.Rows[iRow][5]);
                    newContact["Company"] = Convert.ToString(listTable.Rows[iRow][6]);
                    newContact.Update();
                }
                mySite.AllowUnsafeUpdates = false;
            }
            catch (Exception ex)
            {
                //log exception
            }
            finally
            {
                if (mySite != null) //don't dispose if the site is from SPContext
                {
                    mySite.AllowUnsafeUpdates = false;
                }
            }
  
        }
  
    }
}

Remarks

In the above code
‘GetExcelDataTable’ method takes data from first sheet name i.e get_Item(1). Change this if you want to load from another sheetName
‘InsertIntoList’ method uses SPContext to get the current web object. If you are using the above code where SPContext is not available then
you have create SPWeb object and dispose it in finally block

Conclusion

Hope you understand how to load excel data with interop

Security context in SharePoint 2010

Security context in SharePoint 2010

Security context in SharePoint 2010 

Introduction

In this article we will see various security concepts in SharePoint 2010. There are three main aspects which we have to understand
  • SPContext
  • RunWithElevatedPrivileges
  • AllUnsafeUpdates

SPContext

SPContext class gets the context of the current HTTP request. The static Current property of the SPContext class provides properties that return context information about the current web application, site collection, site, list, list item, and so on.
The following code shows how we can use the properties of the SPContext class
1
2
3
4
SPList currentList = SPContext.Current.List;
SPWeb currentWeb = SPContext.Current.Web;
SPSite currentSite = SPContext.Current.Site;
SPWebApplication currentWebApplication = SPContext.Current.Site.WebApplication;
Note: No need to dispose the objects returned from the SPContext class.

RunWithElevatedPrivileges

If we perform any operation in the server side code that the authenticated user is not authorized to perform, the user receives an Access Denied message.
For example,lets suppose we have written code in a webpart to navigate the subsites from subsites collection.
If any reader user tries to access this webpart page it gives access denied error.
SPSecurity class provides methods and properties for security management. By using the RunWithElevatedPrivileges method of this class, we can run a block of code in an application with elevated permission.
1
2
3
4
SPSecurity.RunWithElevatedPrivileges(delegate()
{
    // implement code here which will run for any user
});
While using security elevation we need to ensure that we create a class instance from within the block of code that is to be executed inside the security elevated code block. Otherwise, the object will be created in the security context of current user but not the elevated permission user.
Note: When we execute the code with RunWithElevatedPrivileges, it will be impersonated with application pool account which is the highest level impersonation
Additional reference: RunWithElevatedPrivileges

AllUnsafeUpdates

Even though our code block is executing with elevated permissions, still to perform updates on the SharePoint object we need to perform one additional task. It is setting the AllowUnsafeUpdates property to true.
Setting this property to true allows our code to bypass security validation when making changes to SharePoint objects.
AllowUnsafeUpdates is to protect from cross-site scripting attacks. There are basically two scenarios where we would need to fiddle with AllUnsafeUpdates value:
• In case of an HTTP POST request, when using RunWithElevatedPrivileges for a user not having sufficient privileges to make changes to SharePoint objects
• In case of an HTTP GET request, when performing any changes to SharePoint objects, even for a user who has the required privileges to perform the operation
When we use SPContext to get the current web object and update values, it will not give error. But, after getting the web or list object from SPContext and if we are trying to get parent object of that, it will certainly give error when updating the values.

Convert word document to pdf file

Convert word document to pdf file

In this post we will see how to convert Microsoft word document to pdf files using interop. This can be used in SharePoint or Asp.net. These methods will support both .doc and .docx files.
What are the points that are covered
  • Generic method which converts single word document to pdf file
  • Generic method which converts all the word documents in a folder to pdf files

Skill Level – Medium


Convert single word document to pdf file

The following method uses Microsoft office interop dll which executes word saveas fuction to save the word document to pdf file
  using Microsoft.Office.Interop.Word;
  using System;
  using System.IO;

  private static void ConvertWordFileToPdf(string WordFilePath, string PdfFilePath)
        {
            Document doc = null;
            // C# doesn't have optional arguments so we'll need a dummy value
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application word = null;
            string sourceFile = "";
            string destinationFile = "";

            try
            {
                // Create a new Microsoft Word application object
                word = new Microsoft.Office.Interop.Word.Application();

                // Get list of Word files in specified directory
                FileInfo wordFile = new FileInfo(WordFilePath);

                word.Visible = false;
                word.ScreenUpdating = false;

                // Cast as Object for word Open method
                Object filename = (Object)wordFile.FullName;

                sourceFile = wordFile.Name;
                destinationFile = "";

                // Use the dummy value as a placeholder for optional arguments
                doc = word.Documents.Open(ref filename, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing);
                doc.Activate();
                object outputFileName = null;

                if (wordFile.FullName.ToUpper().Contains(".DOCX"))
                {
                    outputFileName = wordFile.FullName.Replace(".docx", ".pdf");
                    destinationFile = sourceFile.Replace(".docx", ".pdf");

                }
                else
                {
                    outputFileName = wordFile.FullName.Replace(".doc", ".pdf");
                    destinationFile = sourceFile.Replace(".doc", ".pdf");
                }

                sourceFile = WordFilePath;
                destinationFile = PdfFilePath + "\\" + destinationFile;

                object fileFormat = WdSaveFormat.wdFormatPDF;

                // Save document into PDF Format
                doc.SaveAs(ref outputFileName,
                    ref fileFormat, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing, ref oMissing);

                // Close the Word document, but leave the Word application open.
                // doc has to be cast to type _Document so that it will find the
                // correct Close method.
                object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
                ((_Document)doc).Close(ref saveChanges, ref oMissing, ref oMissing);
                doc = null;

                //there is options to save file in particular location, default is the current folder.
                // So move or replace a file to a new location explicitly
                if (System.IO.File.Exists(destinationFile))
                {
                    System.IO.File.Replace(outputFileName.ToString(), destinationFile, null);
                }
                else
                {
                    System.IO.File.Move(outputFileName.ToString(), destinationFile);
                }

                Console.WriteLine("Success:" + "SourceFile-" + sourceFile + " DestinationFile-" + destinationFile);

                // word has to be cast to type _Application so that it will find
                // the correct Quit method.
                ((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
                word = null;
            }

            catch (Exception ex)
            {
                Console.WriteLine("Error occured while processing");
                Console.WriteLine("Fail:" + "SourceFile-" + sourceFile + " DestinationFile-" + destinationFile + " Error-" + ex.Message);
            }
            finally
            {
                if (doc != null)
                {
                    ((_Document)doc).Close(ref oMissing, ref oMissing, ref oMissing);
                    doc = null;

                }
                if (word != null)
                {
                    ((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
                    word = null;
                }
            }

        }

Usage


ConvertWordFileToPdf(“c:\Users\Adi\Documents\MyInfo.docx”, “D:\Adi\PdfFiles”);

This function converts MyInfo.docx to MyInfo.pdf; saves the converted pdf file to the location ‘D:\Adi\PdfFiles’

Convert all word documents in a folder to pdf file

The following method uses Microsoft office interop dll which converts all the word files in a folder to pdf files
 using Microsoft.Office.Interop.Word;
 using System;
 using System.IO;

 private static void ConvertAllWordFilesToPdf(string WordFilesLocation, string PdfFilesLocation)
 {
  Document doc = null;
  // C# doesn't have optional arguments so we'll need a dummy value
  object oMissing = System.Reflection.Missing.Value;
  Microsoft.Office.Interop.Word.Application word = null;
  try
  {
   // Create a new Microsoft Word application object
   word = new Microsoft.Office.Interop.Word.Application();

   // Get list of Word files in specified directory
   DirectoryInfo dirInfo = new DirectoryInfo(WordFilesLocation);

   FileInfo[] wordFiles = dirInfo.GetFiles("*.doc");

   if (wordFiles.Length > 0)
   {
    word.Visible = false;
    word.ScreenUpdating = false;
    string sourceFile = "";
    string destinationFile = "";
    try
    {
     foreach (FileInfo wordFile in wordFiles)
     {
      // Cast as Object for word Open method
      Object filename = (Object)wordFile.FullName;

      sourceFile = wordFile.Name;
      destinationFile = "";

      // Use the dummy value as a placeholder for optional arguments
      doc = word.Documents.Open(ref filename, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing);
      doc.Activate();
      object outputFileName = null;

      if (wordFile.FullName.ToUpper().Contains(".DOCX"))
      {
       outputFileName = wordFile.FullName.Replace(".docx", ".pdf");
       destinationFile = sourceFile.Replace(".docx", ".pdf");

      }
      else
      {
       outputFileName = wordFile.FullName.Replace(".doc", ".pdf");
       destinationFile = sourceFile.Replace(".doc", ".pdf");
      }

      sourceFile = WordFilesLocation + "\\" + destinationFile;
      destinationFile = PdfFilesLocation + "\\" + destinationFile;

      object fileFormat = WdSaveFormat.wdFormatPDF;

      // Save document into PDF Format
      doc.SaveAs(ref outputFileName,
       ref fileFormat, ref oMissing, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing,
       ref oMissing, ref oMissing, ref oMissing, ref oMissing);

      // Close the Word document, but leave the Word application open.
      // doc has to be cast to type _Document so that it will find the
      // correct Close method.
      object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
      ((_Document)doc).Close(ref saveChanges, ref oMissing, ref oMissing);
      doc = null;

      //there is options to save file in particular location, default is the current folder.
      // So move or replace a file to a new location explicitly
      if (System.IO.File.Exists(destinationFile))
      {
       System.IO.File.Replace(sourceFile, destinationFile, null);
      }
      else
      {
       System.IO.File.Move(sourceFile, destinationFile);
      }

      Console.WriteLine("Success:" + "SourceFile-" + outputFileName.ToString() + " DestinationFile-" + destinationFile);

     }

     // word has to be cast to type _Application so that it will find
     // the correct Quit method.
     ((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
     word = null;
    }
    catch (Exception ex)
    {
     //individual file exception, do not stop but display the error
     //Log this if needed
     Console.WriteLine("Fail:" + "SourceFile-" + sourceFile + "  DestinationFile-" + destinationFile + "#Error-" + ex.Message);
    }
   }
  }
  catch (Exception ex)
  {
   Console.WriteLine("Error occured while processing");
   Console.WriteLine(ex.Message);
  }
  finally
  {
   if (doc != null)
   {
    ((_Document)doc).Close(ref oMissing, ref oMissing, ref oMissing);
    doc = null;

   }
   if (word != null)
   {
    ((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
    word = null;
   }
  }
 } 

Usage

ConvertAllWordFilesToPdf(“c:\Users\Adi\Documents”, “D:\Adi\PdfFiles”);
This function converts all the word files in ‘c:\Users\Adi\Documents’ to pdf files and saves the converted pdf files to

Add, Update and Delete list items using ECMAScript

Add, Update and Delete list items using ECMAScript

In this post we will see how to Add, Update and Delete SharePoint list items with ECMAScript (aka javascript client object model)
  • Add item to SharePoint list
  • Update item of SharePoint list
  • Delete item from SharePoint list

Skill Level – Medium


Add item to SharePoint list

To add an item to the list, use the ListItemCreationInformation object,set the properties using set_item, call the update and ExecuteQueryAsync methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function AddListItem(){
    var ListName = "MyList";
    var context = new SP.ClientContext.get_current(); // the current context is taken by default here
    //you can also create a particular site context as follows
    //var context = new SP.ClientContext('/Sites/site1');
    var lstObject = context.get_web().get_lists().getByTitle(ListName);
    var listItemCreationInfo = new SP.ListItemCreationInformation();
    var newItem = lstObject.addItem(listItemCreationInfo);
    newItem.set_item('Title', 'This is new item');
    // set values to other columns of the list here
    newItem.update();
    context.executeQueryAsync(Function.createDelegate(this, this.onSuccess),
        Function.createDelegate(this, this.onFailure));
  
     function onSuccess() {
  
        alert('Item created: ' + newItem.get_id());
    }
  
    function onFailure(sender, args) {
  
        alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
    }
}

Update Item of SharePoint list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function UpdateListItem()
{
var ListName = "MyList";
var context = new SP.ClientContext.get_current(); // the current context is taken by default here
//you can also create a particular site context as follows
//var context = new SP.ClientContext('/Sites/site1');
 
var lstObject = context.get_web().get_lists().getByTitle(ListName);
this.lstObjectItem = lstObject.getItemById(1);
lstObjectItem.set_item('Title', 'This is updated item');
lstObjectItem.update();
lstObject.set_description("Updated description using ECMAScript");
lstObject.update();
context.executeQueryAsync(Function.createDelegate(this, this.onSuccess),
Function.createDelegate(this, this.onFailure));
}
 
function onSuccess() {
alert('Item udated');
}
 
function onFailure(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

Delete Item from SharePoint list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function DeleteListItem()
{
var ListName = "MyList";
var context = new SP.ClientContext.get_current(); // the current context is taken by default here
//you can also create a particular site context as follows
//var context = new SP.ClientContext('/Sites/site1');
 
var lstObject = context.get_web().get_lists().getByTitle(ListName);
this.lstObjectItem = lstObject.getItemById(1);
lstObjectItem.deleteObject();
 
context.executeQueryAsync(Function.createDelegate(this, this.onSuccess),
Function.createDelegate(this, this.onFailure));
}
 
function onSuccess() {
alert('Item Deleted');
}
 
function onFailure(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

Timer job in SharePoint for specific site

Timer job in SharePoint for specific site

In this post we will see how to create Timer job in SharePoint 2007 / SharePoint 2010.
What are the points that are covered
  • Creating custom Timer job
  • How to execute Timer job for a specific site (without changes to web config and without any static siteurl)
  • How to pass values to property bag of Timer job from feature

SharePoint Timer Job

The following code creates Timerjob class that inherits from SPJobDefinition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using System.Web;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
  
namespace TestSharepointProject
{
    public class TimerJob : SPJobDefinition
    {
        SPWeb mySiteWeb;
        string mySiteUrl = "";
        public TimerJob(SPWebApplication webApp): base("TimerJob", webApp, null, SPJobLockType.ContentDatabase)
        {
            this.Title = "TimerJob";
        }
        public TimerJob():base()
        {
        }
        public override void Execute(Guid targetInstanceId)
        {
            if (!string.IsNullOrEmpty(this.Properties["mySiteUrl"].ToString()))
            {
                mySiteUrl = this.Properties["mySiteUrl"].ToString();
            }
  
            if (!string.IsNullOrEmpty(mySiteUrl))
            {
                using (SPSite mySite = new SPSite(mySiteUrl))
                {
                    using (mySiteWeb = mySite.OpenWeb())
                    {
                        //provide your logic here for the site
                    }
                }
            }
  
        }
    }
}
In the above code,the timer job is getting property “mySiteUrl” and creating the site object. The default constructor is required as in the above code, otherwise error will come.
Now our timer job class is ready and we will see how we can add key value pairs in the property bag of our custom timer job class.
Create a feauture “TimerJobFeatureReceiver” with scope as web. Following is the code for the feauture reciever which adds key values.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
  
namespace TestSharepointProject
{
    public class TimerJobFeatureReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
  
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWeb web = properties.Feature.Parent as SPWeb;
                    web.AllowUnsafeUpdates = true;
                    SPWebApplication webApp = web.Site.WebApplication;
                    foreach (SPJobDefinition job in webApp.JobDefinitions)
                        if (job.Name == "TimerJob") job.Delete();
  
                    string key = "mySiteUrl";
                    string value = web.Url;
  
                    TimerJob tmrJob = new TimerJob(webApp);
                    //remove the key if already exists
                    bool isKeyExists = tmrJob.Properties.ContainsKey(key);
                    if (isKeyExists)
                    {
                        tmrJob.Properties.Remove(key);
                    }
                    tmrJob.Properties.Add(key, value);
                    SPMinuteSchedule schedule = new SPMinuteSchedule();
                    schedule.BeginSecond = 0; //to start immediately
                    // schedule.EndSecond = 59; //use this if timer job is to end after some seconde
                    schedule.Interval = 60; //number of minutes
                    tmrJob.Schedule = schedule;
                    tmrJob.Update();
  
                    web.AllowUnsafeUpdates = false;
                });
            }
            catch (Exception ex)
            {
                //log exception if any
            }
        }
  
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {
                //remove the scheduled job
                SPSecurity.RunWithElevatedPrivileges(delegate()
                 {
                     SPWeb web = properties.Feature.Parent as SPWeb;
                     web.AllowUnsafeUpdates = true;
                     SPWebApplication webApp = web.Site.WebApplication;
                     foreach (SPJobDefinition job in webApp.JobDefinitions)
                         if (job.Name == "TimerJob") job.Delete();
                     web.AllowUnsafeUpdates = false;
                 });
            }
            catch (Exception ex)
            {
                //log exception if any
            }
        }
    }
}
One generic way I generally prefer is; create a custom list. Provide key value columns in the list.
Read the custom list in feature acitvation event and add those values in the timerjob property bag. In this way we can maintain config values to
timer job without any changes to web.config just to read some key values.

Remarks

Make sure that the user with whom we are activating the feature should have valid permission as the code is dealing with timer job.
We may encounters some errors like
Access denied.
at Microsoft.SharePoint.Administration.SPPersistedObject.Update()
at Microsoft.SharePoint.Administration.SPJobDefinition.Update()
at Pages.SurveyFeatureReceiver.<>c__DisplayClass1.b__0()

Its suggestable to activate the feature from command prompt and we won’t be getting the above though both are running with same user.
Following is the quick code to activate or deactivate the feature by stsadm
Activating the feature
stsadm -o activatefeature -fileName TimerJobFeatureReceiver\Feature.xml -url http://adicodes/sites/mysite -force
Deactivating the feature
stsadm -o deactivatefeature -fileName TimerJobFeatureReceiver