Saturday, September 6, 2008

Writing a Timer Job

Scenario:
You want to run some code on a regular interval and decided to write a timer Job.

Sample Timer Job Code:

using System;
using System.Net;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SharePoint.TrainingSamples {

public class SharePointTimerJob:SPJobDefinition {

public SharePointTimerJob():base(){ }

public SharePointTimerJob(string jobName,SPWebApplication webApplication)
:base(jobName, webApplication, null, SPJobLockType.ContentDatabase) {
this.Title = "MyTimerJob";
}

public override void Execute (Guid targetInstanceId) {
foreach (SPSite siteCollection in this.WebApplication.Sites) {
// Code to be executed as a part of Timer Job
foreach (SPSite siteCollection in this.WebApplication.Sites)
{
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];

// get reference to "Tasks" list in the RootWeb of
// the first site collection in the content database
SPList taskList = contentDb.Sites[0].RootWeb.Lists["Tasks"];

// create a new task, and update item
SPListItem newTask = taskList.Items.Add();
newTask["Title"] = DateTime.Now.ToString();
newTask.Update();

}
}
}
}
}
Feature Activation Code:
Now that timer job is ready you need to add it to SharePoint Timer Jobs Store, One way is to add it as a part of Feature Activation
// get a reference to our job class in the GAC
public override void FeatureActivating (SPFeatureReceiverProperties properties) {

SPSite site = properties.Feature.Parent as SPSite;

//This is the timer class you have created above
SharePoint.TrainingSamples.SharePointTimerJob oSharePointTimerJob = new SharePoint.TrainingSamples.SharePointTimerJob("MyTimerJob", site.WebApplication);
// set the execution schedule to every 5 minute
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 5;
oSharePointTimerJob.Schedule = schedule;
//update the job
oSharePointTimerJob.Update();
}
Feature De-Activation Code:
You might want to remove it from SharePoint Timer Jobs Store on de-activation
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 == "MyTimerJob")
job.Delete();
}
}
Articles:
MUST READ : Issues with Timer job , OTHER Helpful links MSDN , Must Read , Andrew Connell

Retrieving list items with CAML

Scenario:
You want to retrieve all the items of list

Code:

SPQuery qry = new SPQuery();

string camlquery = "<OrderBy><FieldRef Name='Country' /></OrderBy><Where>"

+ "<Eq><FieldRef Name='LastName' /><Value Type='Text'>Sandeep</Value></Eq>"

+ </Where>";

qry.Query = camlquery;
Usage:
You can use the above 'qry' object in few different ways
SPListItemCollection listItemsCollection = list.GetItems(qry);


or

DataTable listItemsTable = list.GetItems(qry).GetDataTable();
Additonal Note: This query will return all the columns of the list, so if you are intrested in only a few of the columns then you can use

qry.ViewFields = "<FieldRef Name='FirstName' /><FieldRef Name='LastName' />";
Article:
http://sharepointmagazine.net/technical/development/writing-caml-queries-for-retrieving-list-items-from-a-sharepoint-list

Friday, September 5, 2008

Creating a Custom Action

feature.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="GUIDWithoutBraces"
Title="Site Action Menu Custom Action"
Description="This example shows how you can add new menu to WSS Site Actions"
Version="1.0.0.0"
Scope="Site"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="element.xml" />
</ElementManifests>
</Feature>
element.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
<CustomAction Id="GUIDWithoutBraces"
GroupId="SiteActions"
Location="Microsoft.SharePoint.StandardMenu"
Sequence="1000"
Title="Configure Site"
Description="Click on this link to configure extra settings."
Rights="ViewUsageData"
ImageUrl="_layouts/images/crtsite.gif">
<UrlAction Url="~site/_layouts/Client/CustomPage.aspx"/>
</CustomAction>

<CustomAction
Id="NEWGUID"
Location="Microsoft.SharePoint.StandardMenu"
GroupId="ActionsMenu"
ControlAssembly="Training, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0000000000000000"
ControlClass="Training.NewMenuClass">
</CustomAction>
</Elements>
CodeBehind.cs:
using System; 
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace Training
{
class NewMenuClass : System.Web.UI.WebControls.WebControl
{
protected override void CreateChildControls()
{
base.CreateChildControls();

ToolBarMenuButton siteActionsControl = ToolBarMenuButton.GetMenuControl(this);

switch (siteActionsControl.List.RootFolder.Name)
{
case "Shared Documents":
{
Controls.Add(CreateMenuItem("MenuTitle", "Description", 100, "_layouts/custompage.aspx", "_layouts/images/logo.gif"));
break;
}
}
}

private MenuItemTemplate CreateMenuItem(string Text, string Description, int Sequence, string OnClickUrl, string ImageUrl)
{
MenuItemTemplate menuItem = null;
menuItem = new MenuItemTemplate();
menuItem.ID = Guid.NewGuid().ToString();
menuItem.Text = Text;
menuItem.Description = Description;
menuItem.Sequence = Sequence;
menuItem.ClientOnClickNavigateUrl = OnClickUrl;
menuItem.ImageUrl = ImageUrl;

return menuItem;
}
}
}
Notes:
Possible values for the 'Location' attribute:

Microsoft.SharePoint.ContentTypeTemplateSettings
Microsoft.SharePoint.ContentTypeSettings
Microsoft.SharePoint.Administration.ApplicationCreated
Office.Server.ServiceProvider.Administration (Shared Services/SSP links)
Microsoft.SharePoint.ListEdit.DocumentLibrary
Microsoft.SharePoint.Workflows
NewFormToolbar
DisplayFormToolbar
EditFormToolbar
Microsoft.SharePoint.StandardMenu (SiteActions menu)
Mcrosoft.SharePoint.Create (_layouts/create.aspx )
Microsoft.SharePoint.ListEdit (To edit the properties of a list item)
EditControlBlock (image below)
Articles:
http://blogs.breezetraining.com.au/mickb/2007/03/27/MOSSHowToAddActionsToTheUserInterface.aspx

http://blog.sharepointalist.com/2009/03/moss-central-admin-application-pages-p1.html

Which assemblies need to be in SafeControl List

Doubt:
Why some assemblies need to be in SafeControl list , and other not.

Answer:
Assemblies using 'System.Web' namespace and 'Microsoft.SharePoint.WebControls' need to be in Safe Control list.

Deserializing XML file

Scenario:
You want to serialize the data from a class

XML:


<?xml version="1.0" encoding="utf-8"?>
<Address>
<Address1>One Microsoft Way</Address1>
<City>Redmond</City>
<State>WA</State>
<Zip>98052</Zip>
</Address>

Class:

public class Address {
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
}
Code:
Address oAddress = new Address();
XmlSerializer serializer = new XmlSerializer(typeof(Address));
FileStream file = new FileStream(@"c:\address.xml", FileMode.Open);
oAddress = serializer.Deserialize(file) as Address;

Serializing data

Scenario:
You want to serialize the data from a class

Class:

public class Address {
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
}
XML Output:
<?xml version="1.0" encoding="utf-8"?>
<Address>
<Address1>One Microsoft Way</Address1>
<City>Redmond</City>
<State>WA</State>
<Zip>98052</Zip>
</Address>
Code:
Address oAddress = new Address();
XmlSerializer serializer = new XmlSerializer(typeof(Address));
TextWriter writer = new StreamWriter(@"c:\addresses.xml");
serializer.Serialize(writer, oAddress);
writer.Close();

Site Template vs Site Definition

Site Definition Advantage:

  • Data is stored directly on the Web servers, so performance is typically better.
  • A higher level of list customization is possible through direct editing of a various XML files.
  • Certain kinds of customization to sites or lists can only be done with site definitions, such as introducing new file types, defining view styles, or modifying the drop-down Edit menu.
Site definition Disadvantages:
  • Customization of site definition requires more effort than creating custom templates. ( Not a big difference in effort if planning is proper )
  • Users cannot apply a SharePoint theme through a site definition.
  • Users cannot create two lists of the same type with different default content.
  • Customizing site definitions requires access to the file system of the front-end Web server.
Site Templates Advantages:
  • Site templates are easy to create.
  • Almost anything that can be done in the user interface can be preserved in the template.
  • Site templates can be modified without affecting existing sites that have been created from the templates.
  • Site templates are easy to deploy (Basically just a file upload).
Site Template Disadvantages:
  • Site templates are not created in a development environment.
  • They are less efficient in large-scale environments, not very easy to move them across various environments.
  • If the site definition on which the custom template is based does not exist on the front-end server or servers, the custom template will not work. The reason is that Site Template is a delta file applied on an existing Site Definition.