Tuesday, December 28, 2010

Delete web part from the web part gallery

In case you want to delete the web part as soon as a feature is deactivated, you can write a feature receiver for the same.

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{

//Remove the web part from web part gallery
SPSite site = null;
StringBuilder sb = new StringBuilder();
try
{
using (SPWeb web = properties.Feature.Parent as SPWeb)
{
SPList list = web.Lists["Web Part Gallery"];//site.GetCatalog(SPListTemplateType.WebPartCatalog);

for (int i = list.ItemCount - 1; i >= 0; i--)
{
// format name to look like a feature name
string webpartName = list.Items[i].Name;

webpartName = webpartName.Substring(0, webpartName.IndexOf("."));
// delete web parts that have been added
if ((webpartName == "WPChat") || (list.Items[i].DisplayName.Equals("WPChat")))
{
list.Items[i].Delete();
break;
}
}
}
}
catch (Exception ex)
{
using (StreamWriter w = new StreamWriter("C:\\log.txt"))
{
w.WriteLine(ex.ToString());
}
}
finally
{
if (site != null)
site.Dispose();
}
}

Add entries to web.config using wsp

In order to use your solution to add web.config entries follow the below approach-


Step 1: Create feature folder

Step 2: Create Feature.xml file -

Feature Id="113AEEBD-97B0-411a-B118-F6FE6D232C5E"
Title="IMWEBCONFIG"
Description="This feature modifies the Web Application web.config"
Scope="WebApplication"
ReceiverAssembly="Eversheds.InstantMessaging, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=b0c7276684f0a390 "
ReceiverClass="Eversheds.InstantMessaging.FeatureReceiver.ReceiverWebConfig"
xmlns="http://schemas.microsoft.com/sharepoint/"
/Feature

Step 3: Create feature receiver class
SPWebConfigModification webConfigModifications;

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{

var oWebApp = properties.Feature.Parent as Microsoft.SharePoint.Administration.SPWebApplication;

try
{
if (!oWebApp.IsAdministrationWebApplication)
{
ModifyWebConfigEntries(oWebApp);
}
}
catch (Exception ex)
{
using (StreamWriter w = new StreamWriter("C:\\log.txt"))
{
w.WriteLine(ex.ToString());
}
}
}

public void ModifyWebConfigEntries(SPWebApplication oWebApp)
{
#region Http Module Section

webConfigModifications = new SPWebConfigModification();
webConfigModifications.Path = "configuration/system.web/httpModules";
webConfigModifications.Name = "add[@name='CustomHttpModule']";
webConfigModifications.Sequence = 0;
webConfigModifications.Owner = "addCustomModule";

webConfigModifications.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
webConfigModifications.Value = @"";
oWebApp.WebConfigModifications.Add(webConfigModifications);

#endregion

SPWebService.ContentService.WebApplications[oWebApp.Id].Update();
//Applies the web config settings in all the web application in the farm
SPWebService.ContentService.WebApplications[oWebApp.Id].WebService.ApplyWebConfigModifications();
}

Monday, December 27, 2010

Structure of 12 hive folder in solution


Below is the structure of the 12 folder in the solution for usercontrols, features, images, css

Create list in Feature using list templates

Suppose you have your list templates ready with you. Now you want to deploy the same using a solution. How will you do that using a Feature.

Step 1: Create a Feature folder in your solution
Step 2: Create a folder for your templates say 'ListTemplates' and place all your stp files there.
Step 3: Create a Feature.xml file -

Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Id="93E56B63-EA76-43b7-9068-162DCFA1FAE4"
Title="IMEVUSERLIST"
Description="Deploy user list for Instant Messaging"
Scope="Web"
Hidden="false"
Version="1.0.0.0"
ReceiverAssembly="Eversheds.InstantMessaging,Version=1.0.0.0,Culture=neutral, PublicKeyToken=b0c7276684f0a390"
ReceiverClass="Eversheds.InstantMessaging.FeatureReceiver.ReceiverEVUserList"
ElementManifests
ElementManifest Location="Elements.xml"/
/ElementManifests
Properties xmlns="http://schemas.microsoft.com/sharepoint/"
!-- Instant Messaging Lists --
Property Key="InstantMessagingLists" Value="EVChatImage,EVConfigInfo,EVUserList"/
/Properties
/Feature


Step 3: Create Elements file

?xml version="1.0" encoding="utf-8" ?
Elements xmlns="http://schemas.microsoft.com/sharepoint/"
/Elements

Step 4: Create feature receiver

namespace Eversheds.InstantMessaging.FeatureReceiver
{
public class ReceiverEVUserList : SPFeatureReceiver
{}
}

Override all events. Below is the code for FeatureActivated

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb parentWeb;
SPSite siteCollection;

if (properties.Feature.Parent is SPWeb)
{
parentWeb = (SPWeb)properties.Feature.Parent;
siteCollection = parentWeb.Site;
}
else if (properties.Feature.Parent is SPSite)
{
parentWeb = ((SPSite)properties.Feature.Parent).RootWeb;
siteCollection = (SPSite)properties.Feature.Parent;
}
else
{
throw new Exception("Unable to retrieve SPWeb - this feature is not Site or Web-scoped.");
}

string directory = properties.Definition.RootDirectory;

try
{
if (!directory.EndsWith("\\"))
directory += "\\";
directory += "ListTemplates";

if (System.IO.Directory.Exists(directory))
{
string[] templates = System.IO.Directory.GetFiles(directory, "*.stp", System.IO.SearchOption.TopDirectoryOnly);
SPDocumentLibrary listTemplates = siteCollection.GetCatalog(SPListTemplateType.ListTemplateCatalog) as SPDocumentLibrary;

UploadTemplates(listTemplates, templates);
// Add lists from the List Template Gallery


parentWeb.AllowUnsafeUpdates = true; //get the list of list templates from the web
SPListTemplateCollection customListTemplates = siteCollection.GetCustomListTemplates(parentWeb); //create the connection library using the uploaded list template
//Get list collection
SPListCollection listCollection = parentWeb.Lists;

//Create List EVConfigInfo------------------------
if (ListExists(listCollection, "EVConfigInfo"))
{
//get Guid for list
SPList l = parentWeb.Lists["EVConfigInfo"];
Guid listId = l.ID;
//delete list
parentWeb.Lists.Delete(listId);
}

SPListTemplate stpConfigInfo = customListTemplates["EVConfigInfo"];
parentWeb.Lists.Add("EVConfigInfo", "List for Config Info", stpConfigInfo);


//Create List EVUserList------------------------
if (ListExists(listCollection, "EVUserList"))
{
//get Guid for list
SPList l = parentWeb.Lists["EVUserList"];
Guid listId = l.ID;
//delete list
parentWeb.Lists.Delete(listId);
}

SPListTemplate stpUserList = customListTemplates["EVUserList"];
parentWeb.Lists.Add("EVUserList", "List for User Info", stpUserList);

//Create List EVChatImage------------------------
if (ListExists(listCollection, "EVChatImage"))
{
//get Guid for list
SPList l = parentWeb.Lists["EVChatImage"];
Guid listId = l.ID;
//delete list
parentWeb.Lists.Delete(listId);
}

SPListTemplate stpChatImage = customListTemplates["EVChatImage"];
parentWeb.Lists.Add("EVChatImage", "List for Chat image", stpChatImage);

parentWeb.Update();
}
}
catch (Exception ex)
{
using (StreamWriter w = new StreamWriter("C:\\log.txt"))
{
w.WriteLine(ex.ToString());
}
}
}

#region UploadTemplates
///
/// Method to create Sharepoint Lists from template files
///

///
///
private void UploadTemplates(SPDocumentLibrary templateGallery, string[] templateFiles)
{
if (templateGallery != null)
{
foreach (string template in templateFiles)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(template);
SPQuery query = new SPQuery();
query.Query = string.Format("" + "{0}", fileInfo.Name);
SPListItemCollection existingTemplates = templateGallery.GetItems(query);
int[] Ids = new int[existingTemplates.Count];
for (int i = 0; i < existingTemplates.Count; i++)
{
Ids[i] = existingTemplates[i].ID;
}
for (int j = 0; j < Ids.Length; j++)
{
templateGallery.Items.DeleteItemById(Ids[j]);
} byte[] stp = System.IO.File.ReadAllBytes(template);
templateGallery.RootFolder.Files.Add(fileInfo.Name, stp);
}
}
}
#endregion

private static bool ListExists(SPListCollection collection, string title)
{
bool flag = false;
foreach (SPList list in collection)
{
if (list.Title == title)
flag = true;

}
return flag;
}

Step 5: Deploy using wsp builder. The lists will be created

Populate the web part gallery programatically

Suppose you are deploying everything using solutions. You have lots of webparts. How will you populate the web part gallery using your solution. This will allow the user to just add the web part to the page immediately after deploying wsp.

Step1 - Create a Feature.xml file

Feature Id="D34D00B1-EC5C-4da8-8C50-009CB4B8BB42"
Title="IMCHATFEATURE"
Description="This is the chat Webpart"
Version="12.0.0.0"
Hidden="FALSE"
Scope="Web"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/"
ElementManifests
ElementManifest Location="elements.xml"/
ElementFile Location="WPChat.webpart" /
/ElementManifests
/Feature

Step 2: Create an Element File

Elements xmlns="http://schemas.microsoft.com/sharepoint/"
Module Name="WebPartPopulation" Url="_catalogs/wp" RootWebOnly="TRUE" List="113"
File Url="WPChat.webpart" Type="GhostableInLibrary"
/File
/Module
/Elements

Step 3: Create a .webpart file for your webpart

webParts
webPart xmlns="http://schemas.microsoft.com/WebPart/v3"
metaData
type name="Eversheds.InstantMessaging.WebParts.WPChat, Eversheds.InstantMessaging, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=b0c7276684f0a390 "/type
importErrorMessage>Can not import WPChat/importErrorMessage
/metaData
data
properties
property name="Title" type="string"WPChat/property
property name="Description" type="string"A web part which allows the user to chat/property
/properties
/data
/webPart
/webParts


Step 4: Lastly create the .cs file for your web part

namespace Eversheds.InstantMessaging.WebParts
{
public class WPChat : System.Web.UI.WebControls.WebParts.WebPart
{}
}

Place all files in step1,2 and 3 in your feature folder. Deploy using wsp builder. The cs file should be outside the 12 hive folder.

Your web part will be available for the user in the gallery.

Wednesday, October 6, 2010

Commands to deploy WSP

Using Stsadm

"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o retractsolution -name "Eversheds.Connect.wsp" -immediate -allcontenturls
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o execadmsvcjobs
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o deletesolution -name "Eversheds.Connect.wsp"
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o execadmsvcjobs
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o addsolution -filename "Eversheds.Connect.wsp"
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o execadmsvcjobs
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o deploysolution -name "Eversheds.Connect.wsp" -immediate -allcontenturls -allowGacDeployment -allowCasPolicies -force
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o execadmsvcjobs

Using WSP builder

wspbuilder.exe -WSPName Eversheds.Connect.wsp -BuildWSP false -deploy true


If there are features involved, add commands to activate feature also in this batch file.

Tuesday, October 5, 2010

Create Custom Master page and Code Behind in Sharepoint

This post explains how to create a master page for sharepoint in your code, how to create its code behind and how to deploy both in sharepoint using feature.

First step is how you make your project. You have to make the exact folder structure. Starting from TEMPLATE/FEATURES/[Name of the Feature].
First I have created a Folder structure - Template/Features/CustomMasterPage/
In that I have another folder - MasterPages. In master pages I have two files - CustomMaster.master and CustomMaster.cs. Outside the MasterPages folder, I have two files - Feature.xml and ProvisionedFiles.xml.

You can create the design of the master page in sharepoint designer for ease and copy the same here. The important line in the design page is the inherits attribute

<%@ Master language="C#" Inherits="Eversheds.Connect.TEMPLATE.FEATURES.MASTERPAGE.EvershedsMasterPage, Eversheds.Connect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6624dc3946212ada" meta:progid="SharePoint.WebPartPage.Document" %>

You need to specify the complete name in the inherits attribute. For cs you can make any cs file and include that as page behind for the master page.
I needed a code behind for master page to include logging. My master page handles all exception handling for the entire site.

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging;
using System.Diagnostics;
using Eversheds.Connect.Util;
using Microsoft.SharePoint;

namespace Eversheds.Connect.TEMPLATE.FEATURES.MASTERPAGE
{
public class EvershedsMasterPage : System.Web.UI.MasterPage
{
ScriptManager scriptMan = null;
string _eventLogName = Toolkit.GetEventLogName();
string _eventLogSource = Toolkit.GetEventLogSource();
string _onOffInfo = Toolkit.GetOnOffInfo();
string _eventLogListener = Toolkit.GetEventLogListener();
string _rollingFileListener = Toolkit.GetRollingLogListener();

protected void Page_Init(object sender, EventArgs e)
{
this.Page.Error += new EventHandler(Page_Error);
}

protected void Page_Load(object sender, EventArgs e)
{
//EnsureScriptManager();
Page_Error(sender, e);
}

private void EnsureScriptManager()
{
if (ScriptManager.GetCurrent(this.Page) == null)
{
scriptMan = new ScriptManager();
this.Controls.Add(scriptMan);
}
else
{
scriptMan = ScriptManager.GetCurrent(this.Page);
}
scriptMan.EnablePartialRendering = true;
}

///
/// Page Error to write log entries to event log and rolling file log
///

///
///
void Page_Error(object sender, EventArgs e)
{
try
{
string err="";
//Create an event source if it does not exist
if (!EventLog.SourceExists(_eventLogSource))
{
EventLog.CreateEventSource(_eventLogSource, _eventLogName);
}
//Write to Event log trace listener
// var currErrors = HttpContext.Current.AllErrors;
SPContext currentContext;
try
{
//Getting the current context
currentContext = SPContext.Current;
}
catch (InvalidOperationException)
{
currentContext = null;
}
Exception ex = HttpContext.Current.Error;
if ((currentContext != null) && (ex != null))
{
err = "Sharepoint Internal Error" + ex.Message.ToString();

Logger.Write(err, _eventLogListener, 1, 2000, TraceEventType.Error, _eventLogListener);
//Write info only if the variable is set to on in the config file
if ((_onOffInfo == "on") || (_onOffInfo == "On") || (_onOffInfo == "ON"))
{
using (new Tracer("Trace"))
{
//Write to rolling text file
Logger.Write(err, _rollingFileListener, 2, 4000, TraceEventType.Information, _rollingFileListener);
}
}
}
}
catch (Microsoft.SharePoint.WebPartPages.WebPartPageUserException mex)
{
//Write to Event log trace listener
Logger.Write(mex.Message.ToString(), _eventLogListener, 1, 2000, TraceEventType.Error, _eventLogListener);
//Write info only if the variable is set to on in the config file
if ((_onOffInfo == "on") || (_onOffInfo == "On") || (_onOffInfo == "ON"))
{
using (new Tracer("Trace"))
{
//Write to rolling text file
Logger.Write(mex.Message.ToString(), _rollingFileListener, 2, 4000, TraceEventType.Information, _rollingFileListener);
}
}
}

catch (Exception ex)
{
//Write to Event log trace listener
Logger.Write(ex.Message.ToString(), _eventLogListener, 1, 2000, TraceEventType.Error, _eventLogListener);
//Write info only if the variable is set to on in the config file
if ((_onOffInfo == "on") || (_onOffInfo == "On") || (_onOffInfo == "ON"))
{
using (new Tracer("Trace"))
{
//Write to rolling text file
Logger.Write(ex.Message.ToString(), _rollingFileListener, 2, 4000, TraceEventType.Information, _rollingFileListener);
}
}
}
}
}
}

For logger, you need to configure the Microsoft application blocks on the server. You can find out more information about the same on the below link



Next we need a Feature.xml

Feature Id="8C463F26-AE3C-4309-A284-AC095EB351A9"
Title="EvershedsMasterPage"
Description="Eversheds Custom Master page for use"
Version="12.0.0.0"
Scope="Site"
Hidden="FALSE"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/"
ElementManifests
ElementManifest Location="ProvisionedFiles.xml"
ElementManifests
Feature

Last in the ProvisionedFiles.xml

Elements xmlns="http://schemas.microsoft.com/sharepoint/"

Module Name="OSGMasterPages" Url="_catalogs/masterpage" Path="MasterPages" RootWebOnly="TRUE"

File Url="EvershedsMasterPage.master" Type="GhostableInLibrary"
Property Name="ContentType" Value="$Resources:cmscore,contenttype_masterpage_name;"
Property Name="PublishingPreviewImage" Value="~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/PolarisSample.png, ~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/PolarisSample.png"
Property Name="MasterPageDescription" Value="This is sample master page;"
File
Module
Module Name="MasterPagesModule" Url="_catalogs/masterpage" Path="MasterPages" RootWebOnly="TRUE"

File Url="EvershedsMasterPage.master" Type="GhostableInLibrary"
File
Module
Module Name="PublishingLayoutsPreviewImages" Url="_catalogs/masterpage" IncludeFolders="??-??*" Path="" RootWebOnly="TRUE"
File Url="PolarisSample.png" Name="Preview Images/PolarisSample.png" Type="GhostableInLibrary"
File
Module

Elements

Create a wsp and deploy it to the server. After running the deployment script, activate your feature and the master page would be ready for use.

Saturday, September 25, 2010

How to create AJAX enabled web part in Sharepoint

When we talk about AJAX and sharepoint, there are several problems. Some people believe that if AJAX works with .net then there should not be any problem. But, there is a little problem however, not without a workaround.

The problem with Sharepoint and AJAX is mentioned in the below blog -
http://sharemypoint.wordpress.com/2007/11/11/webpart-and-ajax-second-postback-not-working-in-updatepanel/.

Make the below web.config entries in your web application -
http://zieglers.wordpress.com/2009/02/02/webconfig-entries-for-enabling-ajax-for-sharepoint-2007/

Windows SharePoint Services JavaScript has a “form onSubmit wrapper” which is used to override the default form action. This work is put in place to ensure that certain types of URLs, which may contain double byte characters, will fully work across most postback and asynchronous callback scenarios. The workaround involved registering a script at page startup.

I created an AJAX webpart with timer.

using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace Eversheds.Connect.WebParts
{
[Guid("D1A860C1-7033-4052-AB47-DF979BA14728")]
public class WPContact : System.Web.UI.WebControls.WebParts.WebPart
{
Label label1;
Button button1;
UpdatePanel updatePanel1;
Timer tim;


protected override void OnInit(EventArgs e)
{
base.OnInit(e);
EnsureChildControls();
}

protected override void CreateChildControls()
{
base.CreateChildControls();
bool bDisabled = false;

try
{
//Fix for the UpdatePanel postback behaviour.
EnsurePanelFix();
EnsureUpdatePanelFixups();

updatePanel1 = new UpdatePanel();
updatePanel1.ID = "updatePanel1";
updatePanel1.ChildrenAsTriggers = true;
updatePanel1.UpdateMode = UpdatePanelUpdateMode
.Conditional;
//button1 = new Button();
//button1.ID = "btnClick";
//button1.Text = "Update";
//button1.Click += new EventHandler(button1_Click);
tim = new Timer();
tim.Interval = 2000;
tim.ID = "tim1";
tim.Tick += new EventHandler(tim_Tick);


label1 = new Label();
label1.ID = "lblShowTime";
label1.Text = string.Format("Updatedate:{0}", DateTime
.Now.ToLongTimeString());
updatePanel1.ContentTemplateContainer.Controls.Add(label1);

//updatePanel1.ContentTemplateContainer.Controls.Add(button1);
updatePanel1.ContentTemplateContainer.Controls.Add(tim);
AsyncPostBackTrigger trig = new AsyncPostBackTrigger();
trig.ControlID = tim.ID;
trig.EventName = "Tick";
updatePanel1.Triggers.Add(trig);

this.Controls.Add(updatePanel1);
//this.Controls.Add(label1);
//this.Controls.Add(button1);
}
catch (Exception ex)
{
throw ex;
}
}
void button1_Click(object sender, EventArgs e)
{
this.label1.Text = string.Format("Updatedat:{0}", DateTime
.Now.ToLongTimeString());
}

void tim_Tick(object sender, EventArgs e)
{
try
{
this.label1.Text = string.Format("Updatedat:{0}", DateTime
.Now.ToLongTimeString());
}
catch (Exception ex)
{
throw ex;
}
}

private void EnsurePanelFix()
{
//Fix problem with postbacks and form actions (DevDiv 55525)
if (this.Page.Form != null)
{
String fixupScript =
@"_spBodyOnLoadFunctionNames.push(""_initFormActionAjax"");
function _initFormActionAjax()
{
if (_spEscapedFormAction ==
document.forms[0].action)
{
document.forms[0]._initialAction =
document.forms[0].action;
}
}
var RestoreToOriginalFormActionCore =
RestoreToOriginalFormAction;
RestoreToOriginalFormAction = function()
{
if (_spOriginalFormAction != null)
{
RestoreToOriginalFormActionCore();
document.forms[0]._initialAction =
document.forms[0].action;
}
}";
ScriptManager.RegisterStartupScript(this, typeof(WPContact
), "UpdatePanelFixup", fixupScript, true);
}
}

private void EnsureUpdatePanelFixups()
{
if (this.Page.Form != null)
{
string formOnSubmitAtt = this.Page.Form.Attributes[
"onsubmit"];
if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
{
this.Page.Form.Attributes["onsubmit"] =
"_spFormOnSubmitWrapper();";
}
}
ScriptManager.RegisterStartupScript(this, typeof(WPContact),
"UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action;
_spSuppressFormOnSubmitWrapper=true;", true);
}
}
}

Thursday, July 15, 2010

Create custom web part in .net

In order to deploy webparts on sharepoint server, one approach is to create a custom web part and then just keep including the custom web part on the page and giving the path of you own user control in it as parameter.
Create a project in VS -

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.ComponentModel;

namespace GeneralWebPart
{
public class GeneralWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
public GeneralWebPart()
{ }

private Control _childControl = null;
private string _userControlVirtualPath = string.Empty;
private string _errMessage = string.Empty;

[
Personalizable(),
Category("Virtual Path"),
DefaultValue(""),
WebBrowsable(true),
WebDisplayName("User Control Virtual Path"),
WebDescription("User Control Virtual Path")
]
public string UserControlVirtualPath
{
get { return _userControlVirtualPath; }
set { _userControlVirtualPath = value; }
}
protected override void CreateChildControls()
{
base.CreateChildControls();

if (_userControlVirtualPath != string.Empty)
{
if (_childControl != null) return;
_childControl = Page.LoadControl(_userControlVirtualPath);
if (_childControl != null)
Controls.AddAt(0, _childControl);
}
}

protected override void RenderWebPart(HtmlTextWriter output)
{
if (_errMessage != string.Empty)
output.Write(_errMessage);
if (_userControlVirtualPath != string.Empty ||
_userControlVirtualPath.Equals("") == false)
RenderChildren(output);
}

protected override void RenderChildren(HtmlTextWriter output)
{
try
{
this.EnsureChildControls();
if (this._childControl != null)
this._childControl.RenderControl(output);
}
catch (Exception ex)
{
_errMessage = string.Format(
"Exception Message (RenderWebPart) = {0}
", ex.Message);
}
}
}
}


Deploy this on the server. Moving forward give the path of your user control in this web part.
In order to deploy this, copy the dll to the GAC, make an entry in the web.config's safe controls section. After you add this to the safe controls section, the web part is available in the list of web parts. You can then include it in your web parts.

Implementing Event Handlers in Sharepoint

Here I am sharing with you all, how to implement Event Handler Feature in sharepoint and how to activate it.

Below example shows how to add a simple event handler that prevents items from being deleted from a list. Two procedures are involved in this task:

1. Creating an event handler in Microsoft Visual Studio
2. Adding the event handler as a Feature in SharePoint

To create the event handler in Visual Studio

1. Create a new project in Visual Studio by clicking File, pointing to New, and then clicking Project.
2. In the New Project dialog box, select Visual C# in the Project types box, select Class Library in the Templates box, type DeletingEventHandler in the Name box, and then click OK.
3. In Solution Explorer, select DeletingEventHandler, and click Add Reference on the Project menu.
4. In the Add Reference dialog box, select Microsoft.SharePoint on the .NET tab and then click OK.
5. In the Code Editor, import the Microsoft.SharePoint namespace as follows.

Change the name of the class like DeleteItemEvent and Inherit it from the SPItemEventReceiver class, as follows.

public class DeleteItemEvent : SPItemEventReceiver

Now add code within the class to override the ItemDeleting method given Belowe.

public class DeleteItemEvent : SPItemEventReceiver
{
public override void ItemDeleting(SPItemEventProperties properties)
{
properties.Cancel = true;
properties.ErrorMessage = "Deleting item from" + " " + properties.ListTitle + " " + "is not supported";
}
}

Now go to Project menu in visual studio, in this last option is DeleteItemEvent Properties click the Signing tab, select Sign the assembly, select Choose a strong name key file, and then click .

In the Create Strong Name Key dialog box, type DeletingEventHandler.snk in the Key file name box, optionally specify a password for the key, and then click OK.

To build the project, click Build Solution on the Build menu, or press CTRL+SHIFT+B.

Find the \DeletingEventHandler\bin\Debug folder in the Visual Studio Projects folder, and drag the DeletingEventHandler.dll file to Local_Drive:\WINDOWS\assembly to place the DLL in the global assembly cache.

To add the event handler as a Windows SharePoint Services Feature

1. Create a folder in Local_Drive:/Program Files/Common Files/Microsoft Shared/web server extensions/12/TEMPLATE/FEATURES called DeletingEventHandler.
2. Create a Feature.Xml file in this folder like the following that identifies the Feature and its element manifest file and sets the Feature scope to Web site.

Title="Deleting Event Handler"
Id="GUID"
xmlns="http://schemas.microsoft.com/sharepoint/">





Here generate a GUID by running guidgen.exe located in Local_Drive:\Program Files\Microsoft Visual Studio 8.

The Elements.xml file is given below. It is referenced in Feature.xml file in ElementManifest Location tag.




DeletingEventHandler
ItemDeleting
22500
ItemAddedEvent, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=d6009c72158cb154

ItemAddedEvent.ItemAddedEvent






Here in Name tag you have to give DLL name. In assembly change info of same for that. Find DLL in GAC and right click on DLL and click on property in that give all the information related to assembly.

In Class tag you have to give Namespace.classname.

In the first tag Receivers "ListtemplatedId" means on which list you have to perfom the Event Handler like Document Library, Custom List, PictureLibrary...etc. Here 101 means Document Library. List of ListTemplated Id are given below.

* 100 Generic list
* 101 Document library
* 102 Survey
* 103 Links list
* 104 Announcements list
* 105 Contacts list
* 106 Events list
* 107 Tasks list
* 108 Discussion board
* 109 Picture library
* 110 Data sources
* 111 Site template gallery
* 112 User Information list
* 113 Web Part gallery
* 114 List template gallery
* 115 XML Form library
* 116 Master pages gallery
* 117 No-Code Workflows
* 118 Custom Workflow Process
* 119 Wiki Page library
* 120 Custom grid for a list
* 130 Data Connection library
* 140 Workflow History
* 150 Gantt Tasks list
* 200 Meeting Series list
* 201 Meeting Agenda list
* 202 Meeting Attendees list
* 204 Meeting Decisions list
* 207 Meeting Objectives list
* 210 Meeting text box
* 211 Meeting Things To Bring list
* 212 Meeting Workspace Pages list
* 301 Blog Posts list
* 302 Blog Comments list
* 303 Blog Categories list
* 1100 Issue tracking
* 1200 Administrator tasks list

In command prompt, navigate to \Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN on the local drive, and type each of the following commands to install the Feature in the deployment, activate the Feature on a specified subsite, and reset Microsoft Internet Information Services (IIS) so that the changes take effect:

1. stsadm -o installfeature -filename DeletingEventHandler\Feature.xml
2. stsadm -o activatefeature -filename DeletingEventHandler\Feature.xml -url http://Server/Site/Subsite
3. iisreset

Try to delete a Document in Document Library on the specified Web site to see the effect of the event handler feature. Output will look like this.



If this does not work - try another method of deployment

In Visual Studio, create a console application -

using System.IO;

namespace EventHnadlerdeployment
{
class Program
{

static void Main(string[] args)
{
SPSite siteCollection = new SPSite("http://dhts1:37869");
{
SPWeb site = siteCollection.OpenWeb();
SPList myList = site.Lists["Documents"];

string assemblyName = "DeletingEventHandler,Version=1.0.0.0,Culture=neutral,PublicKeyToken=b033bffae2cfcb26";
string className = "DeletingEventHandler.DeleteItemEvent";
myList.EventReceivers.Add(SPEventReceiverType.ItemDeleting, assemblyName, className);
// myList.EventReceivers.Add(SPEventReceiverType.ItemUpdated, assemblyName, className);
// myList.EventReceivers.Add(SPEventReceiverType.ItemUpdating, assemblyName, className);

SPEventReceiverDefinitionCollection registeredEvents = myList.EventReceivers;

foreach (SPEventReceiverDefinition def1 in registeredEvents)
{
Console.WriteLine("Succesfully added eventhandler:");
}
}
}
}
}
}

In the above code, change the class name, the namespace etc to the namespace of your project. Run the above code. The feature is deployed.

How to move a Sharepoint content database

You have two initial options, doing a backup and restore within MOSS to move the data, or doing it at the SQL/STSADM level. I prefer the latter, as it isn't nearly as inclined to fail and leaves you with more flexibility.

1) Find the content Database,
These are listed under Central Admin->Application Management->Site Collection List
2) Backup the content database,
You could alternatively detach it, and copy it. Just doing a backup in SQL Server Management studio is easier.

3) Restore content database to new server
Copy the BAK file to new server. Create an empty DB in Management Studio, restore from backup, you may need to change an option in the "options" tab of the restore dialog to get it to work. (Overwrite db).
4) Create Web App on new Server
Central Admin->Application Management->Create or extend Web App->Create New Web App.
5) Associate restored DB with new Web App
Central Admin->Application Management->
SharePoint Web Application Management->Content Databases->
Remove Content Database from your new web app.
Now use STSADM to add restored DB to this web app
c:\program files\common files\microsoft shared\web server extentions\12\bin on new server is where you can find the STSADM.
run this command from there.
stsadm -o addcontentdb -url http://yourwebapp:port -databasename yourcontentdb -databaseserver yoursqlserver
6) Run ISSRESET from command prompt

Important :

* Make sure your running the same service pack level on both source and destination sharepoint if possible.
* Make sure you install all webparts, solutions, features, etc on new server before you restore the content database, so that it can find all the features it's looking for
* Make sure you copy any files that may be living in the file system that you need, sometimes people have css/javascript here. (This refers to files in the hive)
* Leave your old site and contentDB intact until you get the backup running on the new server, this way your ok if there is a problem
* DON'T try this with your config database! It won't work

Wednesday, July 14, 2010

Export to excel from Sharepoint Reports

protected void btnSendtoExcel_Click1(object sender, EventArgs e)
{
try
{
if (grdResultView.Rows.Count != 0)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader(
"content-disposition", string.Format("attachment; filename={0}", "KCADetails.xls"));
HttpContext.Current.Response.ContentType = "application/ms-excel";

using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// Create a table to contain the grid
Table table = new Table();
table.GridLines = GridLines.Both;
// add each of the data rows to the table
table.Rows.Add(grdResultView.HeaderRow);
if (grdResultView.Rows.Count != 0)
{
foreach (GridViewRow row in grdResultView.Rows)
{
//GridViewExportUtil.PrepareControlForExport(row);
table.Rows.Add(row);
}
// render the table into the htmlwriter
table.RenderControl(htw);

// render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString());
HttpContext.Current.Response.End();
}
}
}
}
}
catch (Exception ex)
{ }
}

Deploy Timer jobs through STSADM

[For Feature Install]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o installfeature -name MyTimerFeature

Operation completed successfully.

[For Feature Activate]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o activatefeature -name MyTimerFeature -url "http://sgvm03-sgesx01.sg.dupont
.com:22222/" -force

Operation completed successfully.

[For IIS Reset]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>iisr
eset

Attempting stop...
Internet services successfully stopped
Attempting start...
Internet services successfully restarted

[For Deactivate Feature]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o deactivatefeature -name MyTimerFeature -url "http://sgvm03-sgesx01.sg.dupo
nt.com:22222/" -force

Operation completed successfully.
[For Uninstall Feature]

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o uninstallfeature -name MyTimerFeature

Operation completed successfully.

[for Copy .pdb file]

F:\TimerNameSpace\TimerNameSpace\obj\Debug>xcopy TimerNameSpace.pdb \sgvm03-sge
sx01.sg.dupont.com\c$\windows\assembly
Does \sgvm03-sgesx01.sg.dupont.com\c$\windows\assembly specify a file name
or directory name on the target
(F = file, D = directory)? f
F:TimerNameSpace.pdb
1 File(s) copied

F:\TimerNameSpace\TimerNameSpace\obj\Debug>xcopy TimerNameSpace.pdb c:\windows\
assembly\
F:TimerNameSpace.pdb
1 File(s) copied

F:\TimerNameSpace\TimerNameSpace\obj\Debug>dir /w
Volume in drive F is Data01
Volume Serial Number is 186C-CB1F

Directory of F:\TimerNameSpace\TimerNameSpace\obj\Debug

[.] [..]
ResolveAssemblyReference.cache [TempPE]
TimerNameSpace.dll TimerNameSpace.pdb
3 File(s) 113,597 bytes
3 Dir(s) 3,332,431,872 bytes free

Create Timer Job

Creating a Timer job in MOSS
First we need to have a class derived from SPJobDefinition

Below is the skeleton of that class.
namespace TimerNameSpace
{
#region Using
using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
#endregion Using

///
/// Timer service
///
public class MyTimerService : SPJobDefinition
{
#region Constructor

///
/// Initializes a new instance of the TimerService class
///
public MyTimerService()
: base()
{
}

///
/// Initializes a new instance of the MyTimerService class
///
/// Job Title for the timer service
/// Web appication for which this service will run
public MyTimerService(string jobName, SPWebApplication webApp)
: base(jobName, webApp, null, SPJobLockType.ContentDatabase)
{
this.Title = "My Timer";
}
#endregion Constructor

#region Execute

///
/// Overriden Execute method
///
/// guid of the target object
public override void Execute(Guid targetInstanceId)
{
try
{
/// Here the timer logic goes
}
catch (Exception ex)
{
//Log exception
}
}

#endregion Execute
}
}
One this class is ready. Next thing we need to look into is creating a Feature. This feature will internally schedule the timer as a Job and runs it. Below is the snapshot of this class.
namespace TimerNameSpace
{
#region Namespace Inclusions
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
#endregion Namespace Inclusions

///
/// Class is feature receiver for feature to install approval timer service
///
public class MyTimerFeature : SPFeatureReceiver
{
///
/// Notifications job name
///
public string MyTimerFeatureName = "MyTimerServiceFeature";

///
/// Occurs after a Feature is installed.
///
/// An object that represents the properties of the event.
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
}

///
/// Occurs when a Feature is uninstalled.
///
/// An object that represents the properties of the event.
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
}

///
/// Occurs after a Feature is activated.
///
/// An object that represents the properties of the event.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
// register the the current web
SPWeb web = (SPWeb)properties.Feature.Parent;

SPSite site = web.Site;

// make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == this.MyTimerFeatureName)
{
job.Delete();
break;
}
}

MyTimerService myJob = new MyTimerService(this.MyTimerFeatureName, site.WebApplication);

SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 5;
schedule.Interval = 2;

myJob.Schedule = schedule;
myJob.Update();
}

///
/// Occurs when a Feature is deactivated.
///
/// An object that represents the properties of the event.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
// current web
SPWeb web = (SPWeb)properties.Feature.Parent;

SPSite site = web.Site;

// delete the job
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == this.MyTimerFeatureName)
{
job.Delete();
break;
}
}
}
}
}
Similar to SPMinuteSchedule, there is Hourl Schedule also. Use the one as per your requirement.
Once this much is done, we need to create Feature.xml file for the feature we have built and paste it under the Features Folder (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES). Create a folder named MyTimerFeature and under this folder create Feature.xml with the following content.



Creator="Amal Hashim"
Id="{76D2F200-5CA0-4882-B64F-9FC6208C1234}"
Title="MyTimerFeature"
Description="My Timer."
Scope="Web"
Hidden="FALSE"
Version="1.0.0.0"
ReceiverAssembly="MyTimer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=12344ab009fa4028"
ReceiverClass="TimerNameSpace.MyTimerFeature">

You can activate the feature using the Stsadm command as shown below.
stsadm -o installfeature -name MyTimerFeature

For checking whether the timer has activated successfully or not, you can go to the central admin page
Central Administration –> Operations –> Timer Job Status

For debugging Timer Job we add .pdb file with the help of DOS.

Merge word document and upload in a List with attachment

private static void Merge(string filesToMerge, string outputFilename, bool insertPageBreaks, string defaultWordDocumentTemplate)
{
{
object defaultTemplate = @"Normal.dot";
object missing = System.Type.Missing;
object pageBreak = Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak;
object outputFile = outputFilename;

// Create a new Word application
Microsoft.Office.Interop.Word._Application wordApplication = new Microsoft.Office.Interop.Word.Application();

try
{
// Create a new file based on our template
Microsoft.Office.Interop.Word._Document wordDocument = wordApplication.Documents.Add(
ref defaultTemplate
, ref missing
, ref missing
, ref missing);

// Make a Word selection object.
Microsoft.Office.Interop.Word.Selection selection = wordApplication.Selection;

// Loop thru each of the Word documents
string StrMergeDoc = filesToMerge.ToString();
string[] Delimeter = StrMergeDoc.Split(',');
for (int i = 0; i <= Delimeter.Length - 1; i++)
{
string strMDoc = "F:/punit/event handler/EventHnadlerdeployment/EventHnadlerdeployment/" + Delimeter[i].ToString().Trim() + ".doc";
// foreach (string file in filesToMerge)
//{
// Insert the files to our template
selection.InsertFile(strMDoc, ref missing, ref missing, ref missing, ref missing);

//Do we want page breaks added after each documents?
if (insertPageBreaks)
{
selection.InsertBreak(ref pageBreak);
}
}

// Save the document to it's output file.
wordDocument.SaveAs(ref outputFile, ref missing, ref missing, ref missing, ref missing, ref missing
, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing
, ref missing, ref missing);

// Clean up!
wordDocument = null;
}
catch (Exception ex)
{
//I didn't include a default error handler so i'm just throwing the error
//throw ex;
}
finally
{
// Finally, Close our Word application
wordApplication.Quit(ref missing, ref missing, ref missing);
}
} //throw new Exception("The method or operation is not implemented.");
}


private static void uploadfile(SPListItem item)
{
SPAttachmentCollection spAttachmentCollection = item.Attachments;
FileStream fStream = File.OpenRead("C:\\Punit.doc"); //path of the file to upload
byte[] contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
fStream.Dispose();
spAttachmentCollection.Add("Competency.doc", contents);
item.Update();
}
public void MergeDocument(SPListItem item)
{
string defaultWordDocumentTemplate = @"Normal.dot";
string outputFilename = @"C:\Punit.doc";
string filesToMerge = string.Empty;
SPSite site = new SPSite("http://dhts1:22222");
SPWeb web = site.OpenWeb();
web.AllowUnsafeUpdates = true;
SPListItemCollection itemcoll = web.Lists["Creation of Job Description"].Items;
if (itemcoll != null && itemcoll.Count > 0)
{
{
string IndividualContributor = Convert.ToString(item["Individual_x0020_Contributor"]).Replace('#', ' ');
string newIP = IndividualContributor.Remove(0, 1);
string PPL = Convert.ToString(item["PPL"]).Replace('#', ' ');
string newPPL = PPL.Remove(0, 1);
string BFL = Convert.ToString(item["BFL"]).Replace('#', ' ');
string newBFL = BFL.Remove(0, 1);
string STL = Convert.ToString(item["STL"]).Replace('#', ' ');
string newSTL = STL.Remove(0, 1);
filesToMerge = newIP.Trim() + newPPL.Trim() + newBFL.Trim() + newSTL.Trim();
filesToMerge = filesToMerge.Replace(';', ',');
}
}
Merge(filesToMerge, outputFilename, true, defaultWordDocumentTemplate);

}

stsadm command for backup and restore

C:\Program Files>
C:\Program Files>cd "Common Files"

C:\Program Files\Common Files>cd "Microsoft Shared"

C:\Program Files\Common Files\Microsoft Shared>cd "web server extensions"

C:\Program Files\Common Files\Microsoft Shared\web server extensions>cd 12

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12>cd bin

[Backup]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o backup -url "http://sgvm03-sgesx01.sg.dupont.com:22222/" -filename C:\Late
stBackUp\Latestbackup

Operation completed successfully.
[Restore]
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o restore -url "http://dhts1:22222/" -filename C:\LatestBackUp\Latestbackup

Operation completed successfully.

[Export]

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
dm -o export -url "http://sgvm03-sgesx01.sg.dupont.com:55555/teamroom" -filenam
e "c:\export" -includeusersecurity

[Import]
c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsa
m -o import -filename "c:\export.cmp" -url "http://dhts1:55555/teamroomNew"

Monday, July 12, 2010

Creating Report in Sharepoint

Whenever microsoft talks about reports, it talks about the reports created in excel. But, when we talk about creating report of some data that is entered in lists in Microsoft Sharepoint Server, it is a difficult task.

What we have to do is get the entire lists in sharepoint, store them in datatables and then join them.

#region Datatable DocInfo
DataTable dtDocInfo = new DataTable();
SPQuery qDoc = new SPQuery();
DataRow drDocInfo;
dtDocInfo.Columns.Add("Description");
dtDocInfo.Columns.Add("KCAno");
dtDocInfo.Columns.Add("KCAid");

SPListItemCollection docInfoCol;
#endregion

#region Datatable Eval Info
//Data table Dt Eval info

DataTable dtEvalInfo = new DataTable();
DataRow drEvalInfo;

dtEvalInfo.Columns.Add("Evaluation");
dtEvalInfo.Columns.Add("KCAno");
dtEvalInfo.Columns.Add("KCAid");
SPQuery qEval = new SPQuery();
SPListItemCollection evalInfoCol;
#endregion

#region Datatable Audit Finding
DataTable dtAuditFinding = new DataTable();
DataRow drAuditFinding;

dtAuditFinding.Columns.Add("Audit No");
dtAuditFinding.Columns.Add("KCAno");
dtAuditFinding.Columns.Add("KCAid");

SPQuery qAudit = new SPQuery();
SPListItemCollection auditFindingCol;
#endregion

#region Create First Relation

DataSet ds = new DataSet();
ds.Tables.Add(dtDocInfo);
ds.Tables.Add(dtEvalInfo);
DataTable jt = new DataTable("Joinedtable");
jt.Columns.Add("Description", typeof(String));
jt.Columns.Add("Evaluation", typeof(String));
jt.Columns.Add("KCAno", typeof(String));
#endregion

#region Create second relation
//Third table
DataSet thirdDS = new DataSet();
thirdDS.Tables.Add(jt);
thirdDS.Tables.Add(dtAuditFinding);

DataTable finaljt = new DataTable("FinalJoinedtable");
finaljt.Columns.Add("Description", typeof(String));
finaljt.Columns.Add("Evaluation", typeof(String));
finaljt.Columns.Add("KCAno", typeof(String));
//thirdDS.Tables.Add(finaljt);

#endregion

for (int h = 0; h < kcaCount; h++)
{

#region getdata from Audit finding
//Get data from auditFindingList///////////////////////////////////////////////////////////////////////////////////////
qAudit = new SPQuery();
qAudit.Query = @"


" + kcas[h] + @"



";
qAudit.RowLimit = 1;

auditFindingCol = auditFindingList.GetItems(qAudit);
foreach (SPListItem audititem in auditFindingCol)
{
//dtAuditFinding.Clear();
drAuditFinding = dtAuditFinding.NewRow();
drAuditFinding["Audit No"] = audititem["Audit No"];
drAuditFinding["KCAno"] = audititem["KCAno"];
drAuditFinding["KCAid"] = audititem["KCAid"];
dtAuditFinding.Rows.Add(drAuditFinding);
}

#endregion

#region getdata from eval info list
// //Get data from evalInfoList///////////////////////////////////////////////////////////////////////////////////////

qEval = new SPQuery();
qEval.Query = @"


" + kcas[h] + @"



";
qEval.RowLimit = 1;

evalInfoCol = evalInfoList.GetItems(qEval);
//dtEvalInfo = evalInfoCol.GetDataTable();
foreach (SPListItem evalitem in evalInfoCol)
{
//dtEvalInfo.Clear();
drEvalInfo = dtEvalInfo.NewRow();
drEvalInfo["Evaluation"] = evalitem["Evaluation"];
drEvalInfo["KCAno"] = evalitem["KCAno"];
drEvalInfo["KCAid"] = evalitem["KCAid"];
dtEvalInfo.Rows.Add(drEvalInfo);
}

#endregion

#region get data from doc info list
//Get data from docInfoList////////////////////////////////////////////////////////////////////////////////////
qDoc = new SPQuery();
qDoc.Query = @"


" + kcas[h] + @"




";
qDoc.RowLimit = 1;

docInfoCol = docInfoList.GetItems(qDoc);
//dtDocInfo = docInfoCol.GetDataTable();
if (docInfoCol != null)
{
foreach (SPListItem docitem in docInfoCol)
{
//dtDocInfo.Clear();
drDocInfo = dtDocInfo.NewRow();
drDocInfo["Description"] = docitem["Description"];
drDocInfo["KCAno"] = docitem["KCAno"];
drDocInfo["KCAid"] = docitem["KCAid"];
dtDocInfo.Rows.Add(drDocInfo);
}
}
#endregion

#region join table 1 & 2

//ds.Tables.Add(jt);
foreach (DataRow dr1 in dtDocInfo.Rows)
{
foreach (DataRow dr2 in dtEvalInfo.Rows)
{
string Kcano = (string)dr2["KCAno"];
string newKcaNo = "";
if (Kcano.Contains("#"))
{
string[] split = Kcano.Split(new Char[] { '#' });
newKcaNo = split[1].ToString();
}
else { newKcaNo = Kcano; }

if ((dr1.RowState != DataRowState.Deleted) && ((string)dr1["KCAno"] == newKcaNo))
{
try
{
DataRow newt = jt.NewRow();
newt["Description"] = dr1["Description"];
newt["Evaluation"] = dr2["Evaluation"];
newt["KCAno"] = dr2["KCAno"];
jt.Rows.Add(newt);
}
catch (Exception ex)
{ }
}
}
}
#endregion

# region Join table jt and 3

foreach (DataRow dr1 in jt.Rows)
{
foreach (DataRow dr2 in dtAuditFinding.Rows)
{
string Kcano = (string)dr2["KCAno"];
string newKcaNo = "";
if (Kcano.Contains("#"))
{
string[] split = Kcano.Split(new Char[] { '#' });
newKcaNo = split[1].ToString();
}
else { newKcaNo = Kcano; }

if ((dr1.RowState != DataRowState.Deleted) && ((string)dr1["KCAno"] == newKcaNo))
{
DataRow newt = finaljt.NewRow();
newt["Description"] = dr1["Description"];
newt["Evaluation"] = dr1["Evaluation"];
newt["KCAno"] = dr2["KCAno"];
finaljt.Rows.Add(newt);
}
}
}

#endregion

//End loop for KCA's
}

thirdDS.Tables.Add(finaljt);

DataSet FullFinalDs = new DataSet();
FullFinalDs = thirdDS.Clone();
DataRow drfinal = null;
for (int z = 0; z < kcas.Length; z++)
{
DataRow[] foundRows = thirdDS.Tables[2].Select("KCAno = '" + kcas[z] + "'");
if (foundRows.Length > 0)
{
drfinal = FullFinalDs.Tables[2].NewRow();
for (int count = 0; count < thirdDS.Tables[2].Columns.Count; count++)
{
drfinal[count] = Convert.ToString(foundRows[0][count]);
}

FullFinalDs.Tables[2].Rows.Add(drfinal);
}
}
DataView dvnew = FullFinalDs.Tables[2].DefaultView;
if (dvnew.Count == 0)
{
grdResultView.Visible = false;
lblMessage.Visible = true;
lblMessage.Text = "No Records are available for this selection";
}
grdResultView.DataSource = dvnew;
grdResultView.DataBind();
grdResultView.Visible = true;
}