LinkedIn

Thursday, April 28, 2011

Disaster Recovery in SharePoint Server 2010

Overview:


We define disaster recovery as the ability to recover from a situation in which a data center that hosts SharePoint Server becomes unavailable. The disaster recovery strategy that you use for SharePoint Server must be coordinated with the disaster recovery strategy for the related infrastructure, including Active Directory domains, Exchange Server, and Microsoft SQL Server.

The time and immediate effort to get another farm up and running in a different location is often referred to as a hot, warm, or cold standby. Our definitions for these terms are as follows:


Cold standby Second data center that can provide availability within hours or days. Have backups on a regular basis, and has contracts in place for emergency server rentals in another region. You can recover by setting up a new farm in a new location, (preferably by using a scripted deployment), and restoring backups. Or, you can recover by restoring a farm from a backup solution such as Microsoft System Center Data Protection Manager 2007 that protects your data at the computer level and lets you restore each server individually. Often the cheapest option to maintain, operationally.

Often an expensive option to recover, because it requires that physical servers be configured correctly after a disaster has occurred. The slowest option to recover.

Warm standby A second data center that can provide availability within minutes or hours. . A business ships virtual server images to local and regional disaster recovery farms. You can create a warm standby solution by making sure that you consistently and frequently create virtual images of the servers in your farm that you ship to a secondary location. At the secondary location, you must have an environment available in which you can easily configure and connect the images to re-create your farm environment. Often relatively inexpensive to recover, because a virtual server farm can require little configuration upon recovery. Can be very expensive and time consuming to maintain.

Hot standby A second data center that can provide availability within seconds or minutes. A business runs multiple data centers, but serves content and services through only one data center. You can set up a failover farm to provide disaster recovery in a separate data center from the primary farm. An environment that has a separate failover farm has the following characteristics:

• A separate configuration database and Central Administration content database must be maintained on the failover farm.

• All customizations must be deployed on both farms.

• Updates must be applied to both farms, individually.

• SharePoint Server content databases can be successfully asynchronously mirrored or log-shipped to the failover farm

Often relatively fast to recover. Can be quite expensive to configure and maintain.



Backup and recovery overview (SharePoint Server 2010):

The backup architecture and recovery processes that are available in Microsoft SharePoint Server 2010, including farm and granular backup and recovery, and recovery from an unattached content database. Backup and recovery operations can be performed through the user interface or through Windows PowerShell cmdlets. Built-in backup and recovery tools may not meet all the needs of your organization.

Backup and recovery scenarios

Backing up and recovering data supports many business scenarios, including the following:

• Recovering unintentionally deleted content that is not protected by the Recycle Bin or versioning.

• Moving data between installations as part of a hardware or software upgrade.

• Recovering from an unexpected failure.



Backup architecture

• SharePoint Server 2010 provides two backup systems: farm and granular.

Farm backup architecture

• The farm backup architecture in SharePoint Server 2010 starts a Microsoft SQL Server backup of content and service application databases, writes configuration content to files, and also backs up the Search index files and synchronizes them with the Search database backups.

Granular backup and export architecture

• If you are running SQL Server Enterprise, the granular backup system can optionally use SQL Server database snapshots to ensure that data remains consistent while the backup or export is in progress. When a snapshot is requested, a SQL Server database snapshot of the appropriate content database is taken, SharePoint Server uses it to create the backup or export package, and then the snapshot is deleted. Database snapshots are linked to the source database where they originated. If the source database goes offline for any reason, the snapshot will be unavailable.

References:
http://technet.microsoft.com/en-us/library/ff628971.aspx
http://technet.microsoft.com/en-us/library/ee663490.aspx

Thursday, April 14, 2011

SharePoint 2010 custom masterpage with code behind file

Master Page code behind should like this:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace MasterPageWithCodeBehind.MasterPageModule

{

public class _starter : MasterPage

{

protected System.Web.UI.HtmlControls.HtmlGenericControl divRibbonContainer;
protected Label Label1;

protected void Page_Load(object sender, EventArgs e)
{

     divRibbonContainer.Visible = false;
     Label1.Text = "Hello World!";
}

}

}
 
In the application pages you should have a attribute like this:
Add the following Inherits attribute:
Inherits :
To combine the code-behind file with the masterpage there need to be an attribute added to the masterpage directive.
The following data is needed:
■Namespace of the class & Type/Class name (these need to be seperated by a dot) (MasterPageWithCodeBehind.MasterPageModule._starter)

■Strongname/Assembly in my case was this the same as the projectname (MasterPageWithCodeBehind)

■Version (Version=1.0.0.0)

■Culture (Culture=neutral)

■PublicKeyToken (PublicKeyToken=f8a88530fbc7b81b)In the masterpage navigate to the following:

In our case the Inherits would contain:
MasterPageWithCodeBehind.MasterPageModule._starter, MasterPageWithCodeBehind, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f8a88530fbc7b81b
 
Deploy your SharePoint 2010 project and load the default site.Your ribbon should be gone and a text like Hello World! should be visible.
Refer the following link for details:
http://rburgundy.wordpress.com/2010/03/10/sharepoint-2010-custom-masterpage-with-code-behind-file-%e2%80%93-part-2/

Friday, April 8, 2011

Rendering a document file from a document library on web part in HTML format

The following is the code for rendering a document file in a document library in sharepoint as html file in a iFrame in a web part. This will be very userfull if you want to render a document in readonly mode on browser.
string url = SPAccessLayer.DownloadAndConvertFile(url of document in the document library);


string name = "QueryStringPageViewer_" + this.UniqueID;

output.AddAttribute(HtmlTextWriterAttribute.Id, name, false);

output.AddAttribute(HtmlTextWriterAttribute.Name, name, false);

output.AddAttribute(HtmlTextWriterAttribute.Width, "100%", false);

output.AddAttribute(HtmlTextWriterAttribute.Height, "60%", false);

output.AddAttribute(HtmlTextWriterAttribute.Height, "60%", false);

output.AddAttribute(HtmlTextWriterAttribute.Src, url, false);

output.AddAttribute("ddf_src", url, false);

output.AddAttribute("frameBorder", "0", false);

output.RenderBeginTag(HtmlTextWriterTag.Iframe);

output.RenderBeginTag(HtmlTextWriterTag.Div);

output.Write("IFrames not supported by this browser");

output.RenderEndTag();

output.RenderEndTag();


SPAccessLayer.cs:

public static string DownloadAndConvertFile( string itemUrl)
{
string DestFile = string.Empty;
string DestHtmlFile = string.Empty;
string listFileName = string.Empty;
string pDestFilePath = @"C:\Inetpub\wwwroot\wss\VirtualDirectories\4568\Doc";
string pDestHtmlPath = @"C:\Inetpub\wwwroot\wss\VirtualDirectories\4568\HTML";
string DestinationHTMLFilePath = ConfigurationSettings.AppSettings["DestinationHTMLFilePath"];
string DocumentDownloadedPath = ConfigurationSettings.AppSettings["DocumentDownloadedPath"];
pDestFilePath = DocumentDownloadedPath;
pDestHtmlPath = DestinationHTMLFilePath;
SPListItem aItem = SPContext.Current.Web.GetListItem(itemUrl);
if (aItem != null)
{
listFileName = aItem["FileLeafRef"].ToString();
if (listFileName.ToUpper().EndsWith("X"))
listFileName = listFileName.Substring(0, listFileName.Length - 1);
byte[] byteFile = aItem.File.OpenBinary();

//HttpContext.Current.Response.Write(DestFile);


if (listFileName.Contains(".doc"))
{
DestFile = pDestFilePath + listFileName;
FileStream fStream = File.Create(DestFile);
fStream.Write(byteFile, 0, byteFile.Length);
fStream.Close();
DestHtmlFile = OfficeUtility.ConvertWordToHTML(listFileName, pDestFilePath, pDestHtmlPath);
}
else
{
DestFile = @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\MetropolisDocuments\HTMLFiles\" + listFileName;
FileStream fStream = File.Create(DestFile);
fStream.Write(byteFile, 0, byteFile.Length);
fStream.Close();
DestHtmlFile = listFileName;
}
}
//HttpContext.Current.Response.Write(DestHtmlFile);
return pDestHtmlPath + DestHtmlFile;
}

Could not load type 'System.Data.Services.Providers.IDataServiceUpdateProvider'

If you are getting the following error message: Could not load type 'System.Data.Services.Providers.IDataServiceUpdateProvider' from assembly 'System.Data.Services, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The issue is with the ADO.Net Services v1.5. Please refer the link below for solution: http://blog.hompus.nl/2010/03/26/could-not-load-type-idataserviceupdateprovider-when-using-rest-with-sharepoint-2010/

Friday, June 18, 2010

Calculated Column to Display Year in Sharepoint List


=TEXT([Due Date],"yyyy")


Restricting Menu Items in ListView

Add the following javascript lines in the Edit Page of the list from sharepoint designer. 

_spBodyOnLoadFunctionNames.push("hideListViewToolbarItems('Edit in Datasheet','export to Spreadsheet','create column','view rss feed','settings:create view')");







function hideListViewToolbarItems()


{






var menuItem;


var menuItemName;


var menuItemIndex=-1;


var menuItemNames=new Array("edit in datasheet",


"open with windows explorer",


"connect to outlook",'export to spreadsheet','view rss feed','alert me'


,"create column","settings:create view","list settings",


"document library settings","explorer view","all documents",


"all items","modify this view",


"view:create view","new document",


"new item","new folder","upload document",


"upload multiple documents");


var menuItems = new Array("EditInGridButton",


"OpenInExplorer","OfflineButton",


"ExportToSpreadsheet","ViewRSS",


"SubscribeButton","AddColumn",


"AddView","ListSettings","ListSettings",


"View1","DefaultView",


"DefaultView","ModifyView","CreateView",


"New0","New0",


"NewFolder","Upload","MultipleUpload");






var allMenuItems = document.getElementsByTagName('ie:menuitem');


for(var i = 0; i < hideListViewToolbarItems.arguments.length; i++ )


{


menuItemName= hideListViewToolbarItems.arguments[i].toLowerCase();


for (j=0; j < menuItemNames.length; j++)


{


if(menuItemNames[j]==menuItemName)


{


menuItemIndex = j;


break;


}


}






menuItem=menuItems[menuItemIndex];






for (var l = 0; l < allMenuItems.length; l++)


{


if(menuItemName.indexOf(":")!=-1)


{


menuItemName = menuItemName.split(":")[1];


}


if (allMenuItems[l].id.indexOf(menuItem)!=-1


&& allMenuItems[l].text.toLowerCase() == menuItemName)


{


// For FireFox Compatibility


var parentNodeOfMenuItem = allMenuItems[l].parentNode;


parentNodeOfMenuItem.removeChild(allMenuItems[l]);


break;


}


}


}


}




Connected WebParts in WSS 3.0 and MOSS 2007

ASP.NET 2.0 web part connection framework contains a set of predefined interfaces and transformers for these predefined Consumer and Provider Interfaces.

The following is an overview of the predefined interfaces that are available in the ASP.NET 2.0


web part connections framework (all interfaces are located in the System.Web.UI.WebControls.

WebParts namespace):
 
• IWebPartField interface: This interface is used when web parts want to exchange a single


value. This interface is comparable to cell interfaces in the SharePoint 2003 web part connection

framework. Classes supporting the web part field interface are very suitable for

implementing data enhancement scenarios.

• IWebPartRow interface: This interface is used when web parts want to exchange a row of

information. This interface is comparable to row interfaces in the SharePoint 2003 web part

connection framework. Classes supporting the web part row interface are very suitable for

implementing master/detail scenarios.


• IWebPartTable interface: This interface is used when web parts want to exchange an entire

list of data (a set of rows). This interface is comparable to list interfaces in the SharePoint

2003 web part connection framework. Classes supporting the web part table interface are

very suitable for implementing alternate-view scenarios.

• IWebPartParameters interface: This interface is used when web parts want to exchange a

list of parameters (or, if you will, a property bag containing various values). This interface

is comparable to the ParamsOut interfaces of the SharePoint 2003 web part connection

framework.

ProviderWebPart:

namespace TestWebPartConnection


{

[ToolboxData("<{0}:ProviderWebPart runat=server>")]

[Guid("59bf0dbb-e31a-4d6b-8295-76f4def28470")]

public class ProviderWebPart : WebPart, IWebPartField

{

TextBox InputBox;

Button SubmitButton;



[ConnectionProvider("Web part Connection Provider")]

public IWebPartField GetWPConnectFieldProvider()

{

return this;

}

public void GetFieldValue(FieldCallback callback)

{

callback.Invoke(InputBox.Text);

}

public PropertyDescriptor Schema

{

get

{

return TypeDescriptor.GetProperties(this)["Web part Connection Provider"];

}

}





protected override void Render(HtmlTextWriter output)

{

//Make sure that all necessary child controls are created

//EnsureChildControls();

CreateChildControls();



//Render the TextBox

InputBox.Enabled = true;

output.Write("Enter the text ");

InputBox.RenderControl(output);



//Create a break

output.RenderBeginTag(HtmlTextWriterTag.Br);

output.RenderEndTag();

//Render the button

SubmitButton.Enabled = true;

SubmitButton.RenderControl(output);





}



///

/// Creates all the user interface controls necessary for the web part

///


protected override void CreateChildControls()

{

//Create The Text Bob

InputBox = new TextBox();

InputBox.ID = "InputBox";

InputBox.Enabled = false;

//Add to the Control List

Controls.Add(InputBox);



//Create the button

SubmitButton = new Button();

SubmitButton.ID = "SubmitButton";

SubmitButton.Text = "Submit";

SubmitButton.Enabled = false;

//Add to the control list

Controls.Add(SubmitButton);



SubmitButton.Click += new EventHandler(SubmitButtonClick);

}



private void SubmitButtonClick(object sender, EventArgs e)

{

}

}

}
 
Consumer Webpart:
 
namespace TestWebPartConnection


{

[ToolboxData("<{0}:ConsumerWebPart runat=server>")]

[Guid("18789938-92d3-40ca-bd44-014644f7c884")]

public class ConsumerWebPart : System.Web.UI.WebControls.WebParts.WebPart

{

TextBox txtBox;
string name = string.Empty;


public string Name

{

get { return name; }

set { name = value; }

}



public ConsumerWebPart()

{

}



[ConnectionConsumer("Web Part Consumer")]

public void GetWPConnectedProviderInterface(IWebPartField connectProvider)

{

FieldCallback callback = new FieldCallback(ReceiveField);

connectProvider.GetFieldValue(callback);

}



public void ReceiveField(object objField)

{

if (objField != null)

{

this.Name = (string)objField;

if (this.Name != "")

txtBox.Text = this.Name;

}

}


protected override void CreateChildControls()

{

base.CreateChildControls();

Label label = new Label();

label.Text = "Name:";

txtBox = new TextBox();

Controls.Add(txtBox);



// TODO: add custom rendering code here.



// this.Controls.Add(label);

}

}

}

Friday, June 11, 2010

Using Ajax Update Progress in ASP.Net

The following code snippets illusrate using ajax UpdateProgress in ASP.Net Applications:
Defaut.aspx



Default.aspx.cs

protected void Button1_Click(object sender, EventArgs e)


{

System.Threading.Thread.Sleep(5000);

}

Delete listitems from Sharepoit List

We cannot use the following code, we may get the following error:
"Collection was modified; enumeration operation may not execute."


using (SPSite site = new SPSite("http://server")) {
using (SPWeb web = siteCollection.OpenWeb()) {
SPList list = web.Lists["MyList"];

foreach (SPListItem item in list.Items) {
item.Delete();
}
}
}

We also cannot use the following code:

for (int i = 0; i < list.Items.Count; i++) {
list.Items.Delete(i);
}



The correct code is as follows:
The correct method for deleting list items is to use a decrementing For loop.

for (int i = list.Items.Count - 1; i >= 0; i--) {
list.Items.Delete(i);
}

For details refer the following link.

Programmatically Create a Sharepoint List (SPList)

The following code snippet can be used to create a list in sharepoint site. The following example I have illustrated only DocumentLibrary creation.

public static bool CreateSPList(SPWeb web, string listName, SPListTemplateType type)
{
bool create = false;
try
{
if (type == SPListTemplateType.DocumentLibrary)
{
web.Lists.Add(listName, listName, SPListTemplateType.DocumentLibrary);
return true;
}
}
catch (Exception ex)
{
return false;
}
return create;
}

Programmatically Create or Get Folder in Sharepoint

To create or get a folder from Sharepoint Site the following code snippet can be used:

public static SPFolder CreateORGetFolder( SPWeb web, string listName, string folderUrl)
{
SPList targetList = web.Lists[listName];

if (string.IsNullOrEmpty(folderUrl))
return targetList.RootFolder;
SPFolder folder = targetList.ParentWeb.GetFolder(web.Url + "/" + targetList.RootFolder.Url + "/" + folderUrl);

if (!folder.Exists)
{
if (!targetList.EnableFolderCreation)
{
targetList.EnableFolderCreation = true;
targetList.Update();
} // We couldn't find the folder so create it
string[] folders = folderUrl.Trim('/').Split('/');
string folderPath = string.Empty;
for (int i = 0; i < folders.Length; i++)
{
folderPath += "/" + folders[i];
folder = targetList.ParentWeb.GetFolder(web.Url + "/" + targetList.RootFolder.Url + folderPath);

if (!folder.Exists)
{
SPListItem newFolder = targetList.Items.Add("" , SPFileSystemObjectType.Folder,folderUrl);
newFolder.Update();
folder = newFolder.Folder;

}
}
}
// Still no folder so error out
if (folder == null)
throw new SPException(string.Format("The folder '{0}' could not be found.", folderUrl));
return folder;


}