Monday, April 26, 2010

Attached Event Receiver only to a single list

Hi,

As we Event Receivers are very useful in SharePoint, but there is a hurdle associated with it. That is attaching an Event Receiver only to a single list.

Normally we attached the Event Receiver with the help of ListTemplateId, the syntax is:


< listtemplateid="104">
here 104 means the announcements list. You can view the other ListTemplateIds here.

For installing an Event Receiver only for a single list we can use the following approaches:

  1. Using Feature Activated method
  2. Through custom content type
  3. Defining a custom List Template

Here, we are following the first approach. The steps are described below:

1) In the Visual Studio, we first create a "Class Library" project. Inherit SPItemEventReceiver class by adding the reference to SharePoint.dll

2) Then define your custom logic for any events (ItemAdded, ItemUpdated etc) in the Event Receiver.

3) Sign the assembly, (sn -k)

4) Built the project and drag the dll to GAC.

5) Very important, we do not require any Feature.xml or elements.xml for this event receiver.

6) Add another "Class Library" project in the same solution. Inherit SPFeatureReceiver class by adding the reference to SharePoint.dll

7) Now, add the following code to add the Event Receiver (that already drag to GAC) , for a particular list.


public class ReceiverBinder: SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb objCurrentWeb = properties.Feature.Parent as SPWeb)
{
SPList objTargetList = objCurrentWeb.Lists["Target List"];

string strEventReceiverAssembly = "GenerateFormHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e6d3b324481b2ea7";

string strEventReceiverClass = "GenerateFormHandler.GenerateForm";

objTargetList.EventReceivers.Add(SPEventReceiverType.ItemAdded,
strEventReceiverAssembly,
strEventReceiverClass);
}
}

8) Sign the assembly (sn -k)

9) Built the project and drag the dll to GAC.

10) IISReset

11) Now, create a Feature.xml file as following and place the under
12 Hive\Templates\Features\MyFeatureName\Feature.xml



< ?xml version="1.0" encoding="utf-8" ? >
< id = "{DE7FE855-8071-4722-A102-BE8B9CBFFFCA}" title="Sample Title Description=" scope="Web" hidden="FALSE" xmlns="http://schemas.microsoft.com/sharepoint/" receiverassembly="EventReceiverBinder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd7f95539fcc1e97" receiverclass="EventReceiverBinder.ReceiverBinder">
< /Feature >



12) Very important, in the above feature,xml file, the last two elements, ReceiverAssembly and ReceiverClass calls the assembly from GAC, where we defined the FeatureActivated method.

13) Install and Activate the feature using stsadm command

14) Test the target list, to check the Event Receiver.

That's all, Thank you,
Soumyendra

Sunday, April 25, 2010

IPL Finished Finally

Thank God!!! IPL is finally over. And Chennai becomes the champion. But I realize that, I already wasted a large amount of time by watching those matches. As the tournament is over, now I can concentrate on other important stuffs.

As I am staying in Delhi, by default I am supporting team Delhi. But, due to inconsistent performance they are not able to make it to semi-finals. Since Delhi is not a part of semi-finals, we simply not caring about the other teams playing. The song at this moment:

Koyi farq ne albatta
Koyi farq ne albatta
...
Koyi kaise vi khelle
Hum le kiyon jhamele
Hum sab ko support kare kiyon
Keya hum hain ittne Velle !!!
...
Koyi farq ne albatta
Koyi farq ne albatta
...

(courtesy: Radio Mirchi)

Monday, April 19, 2010

Programmatically create a new form in the Form Library in SharePoint

As you will learn that, creating a new form from a from library in SharePoint is not that easy as compared to Document Library. Because in a Form Library the template stored in XSN formate and you need to first extract the xml out of it.

In the first section, we will create the instance of Form Library of a SharePoint site.

SPDocumentLibrary list = null;
using (SPSite objSite = new SPSite("http://soumyendra:555/Forms"))
{
using (SPWeb objWeb = objSite.OpenWeb())
{
list = objWeb.Lists["Person Address"] as SPDocumentLibrary;
}
}

here "Person Address" is the name of the form library.

Next we will pick the template file attached to the form library. We can get that by using SPList.DocumentTemplateUrl property.

Then we need to extract the template file (XSN) using some extract utility. Here I am using CabinetExtractAndCompress. You can download the utility from Code Project and use it.

Then, by using the utility we first create a physical directory and extract the XSN file. After that, by using File Stream object, we read the file content and get the byte array.

byte[] data = null;
SPFile file = list.ParentWeb.GetFile(list.DocumentTemplateUrl);
Extract cab = new Extract();
string szFolder = string.Concat(System.IO.Path.GetTempPath(), list.Title, "\\");

if (!Directory.Exists(szFolder))
Directory.CreateDirectory(szFolder);

cab.ExtractStream(file.OpenBinaryStream(), szFolder);
FileStream fs = new FileStream(szFolder + "template.xml", FileMode.Open);
try
{
data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
}
finally
{
fs.Close();
}


Next, we will have the MomoryStream to convert the byte array to a XML document. This xml document can be used for updating the values of the fields in the document.

MemoryStream inStream = new MemoryStream(data);
XmlTextReader reader = new XmlTextReader(inStream);
XmlDocument xd = new XmlDocument();
xd.Load(reader);
reader.Close();
inStream.Close();

string strLibraryUrl = "http://soumyendra:555/Forms/" + list.DocumentTemplateUrl;


This is a very important step. Since we are using a different file as a source compared to the file uploaded in the form library, we need to update the reference as well.

for (int index = 0; index <>
{
if (xd.ChildNodes[index].Name == "mso-infoPathSolution")
{
string sHref = string.Format("href=\"{0}\"", strLibraryUrl);
Regex regEx = new Regex("href=\".*\"");

if (regEx.IsMatch(xd.ChildNodes[index].Value))
{
xd.ChildNodes[index].Value = regEx.Replace(xd.ChildNodes[index].Value, sHref);
}
else
{
xd.ChildNodes[index].Value = string.Concat(xd.ChildNodes[index].Value, sHref, ' ');
}
}
}

The following steps are for updating the fields in the InfoPath form. We need to loop through the child elements of the form and update the values of the form as required.

//gets the root element from the xml document XmlElement
root = xd.DocumentElement;
for (int index = 0; index <>
{
if (root.ChildNodes[index].Name == "my:Name")
{
root.ChildNodes[index].InnerText = "Somu";
}
else if (root.ChildNodes[index].Name == "my:Address")
{
root.ChildNodes[index].InnerText = "Delhi";
}
else if (root.ChildNodes[index].Name == "my:Phone")
{
root.ChildNodes[index].InnerText = "123456";
}
else if (root.ChildNodes[index].Name == "my:Email")
{
root.ChildNodes[index].InnerText = "somu@gamil.com";
}
}

The final step is to save the file back in the form library. For this we create the instance of the list and Add the file as follows.

using (SPSite objSite = new SPSite("http://soumyendra:555/Forms"))
{
using (SPWeb objWeb = objSite.OpenWeb())
{
// saves the XML Document back as a file
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
SPFile newFile = objWeb.Folders["Person Address"].Files.Add("Somu.xml", (encoding.GetBytes(xd.OuterXml)), true);
}
}


The above post created with the help of Daniel Halan. Please let me know if you have ant doubts on the above mention steps.

Thanks,
Soumyendra