Wednesday, July 22, 2009

SharePoint Site Backup and Restore using STSADM

Scenario: Backup sitecollection and restore it on a different server or same server.

Preface: Lets build some simple script (batch) files here. First declare the constants. Notice the BACKUPFILENAME variable. That would build the file name as YYYY_MM_DD_BACKUP.BAK

Code:

@SET STSADM="c:\program files\common files\microsoft shared\web server extensions\12\bin\stsadm"
@SET MAINSITEURL="http://servername"
@SET BACKUPFILENAME="C:\SiteBackUp\%date:~10,4%_%date:~4,2%_%date:~7,2%_backup.bak"

Backup Commands: Before you take the backup, ensure the Site has 'none' lock. However, when you are ready to run the backup... make sure you make the site lock to 'readonly' so that no further changes can occur.

@echo off
Echo ------------------------------------------------------------------

Echo Getting Site Lock
stsadm -o getsitelock -url %MAINSITEURL%

Pause

Echo Setting Site Lock to ReadOnly
stsadm -o setsitelock -url %MAINSITEURL% -lock readonly

Echo Backing up the top level site
stsadm -o backup -url %MAINSITEURL% -filename %BACKUPFILENAME% -overwrite

Echo Setting Site Lock to None
stsadm -o setsitelock -url %MAINSITEURL% -lock none

Echo ------------------------------------------------------------------
Pause please press any key to continue...

Restore Commands: Use the below script to restore the backed up site onto the new site collection on a new machine.


Echo Getting Site Lock
stsadm -o getsitelock -url %MAINSITEURL%

Pause
@echo off
Echo ------------------------------------------------------------------

Echo Setting Site Lock to none
stsadm -o setsitelock -url %MAINSITEURL% -lock none

Echo Restoring the top level site
stsadm -o restore -url %MAINSITEURL% -filename %BACKUPFILENAME%

Echo Setting Site Lock to None
stsadm -o setsitelock -url %MAINSITEURL% -lock none

Echo ------------------------------------------------------------------
Pause please press any key to continue...



Output: In case the target site does not exist Restore commands would create a new site collection (if it were a different server). If restoring on the same server, you have to use '-override' parameter or have to create a new content database for that Site Collection and then restore.

Ensuring SharePoint Success

Dux Raymond will be hosting a mentoring workshop "Ensuring SharePoint Success: How to Effectively Deliver the Promise of SharePoint" on August 19-21, 2009. In this unique, one time event, he'll be joining by leading SharePoint thought leaders (Paul Culmsee, Andrew Woody and Ruven Gotz) in Organizational Change, Project Management, Requirements Development and Agile Methodology from around the world mentoring you to make sure you can deliver SharePoint success. Not only will they teach key concepts and theories, they'll provide real-world templates, checklists, project artifacts and provide group + 1 on 1 mentoring sessions with the participants!


Check out further details here.

RightsSensitiveVisibilityHelper UserHasRights

Scenario: Find whether the current user has permissions for a specified SPList object

Output:
true if the current user has permissions for the object; otherwise, false.

Code:

public static bool UserHasRights (
PermissionContext permissionContext,
SPBasePermissions permissions,
PermissionMode permissionMode,
SPList contextList
)

Where,
permissionContext: value that indicates the context object to which a permission mask is applied.

permissions: An SPBasePermissions value that specifies the built-in permissions available in

permissionMode: A PermissionMode value that specifies whether the user must have all of the rights specified in the permission mask to view a link, or only one of the rights specified in the permission mask.

contextList: The SPList object to evaluate.

Tuesday, July 14, 2009

Adding and Removing a button to the Ribbon ( SharePoint 2010 )

*** Please view the disclaimer before you proceed ***

Scenario: Adding and Removing a button on the Ribbon. You can define the location on the Ribbon where you want the button to appear. Follow the below method to add a new button / remove the button to the Library tab in the Actions group for a document library.

How-To:

    1. Create a folder under 14 hive\Template\Features (SharePoint 2010 will have 14 hive similar to that of 12 in WSS / MOSS 2007) RibbonButton
    2. As seen in the previous post create the feature.xml
    3. Create a blank xml file, manifest.xml and add the below content (Adding Button) to it and Save it.
    4. Deploy the customization using Windows PowerShell as shown in my previous blog.
    5. Test it by navigating to the document library in your site / sub site and clicking on the library tab > Actions group > New Button button.
    6. To remove the button replace the content in the manifest.xml with the Removing Button content mentioned below.

Adding Button:



<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="Ribbon.Library.Actions.AddAButton"
Location="ViewToolbar"
RegistrationId="101"
RegistrationType="List"
Title="Add a Ribbon Button">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition
Location="Ribbon.Library.Actions.Controls._children">
<Button Id="Ribbon.Library.Actions.NewRibbonButton" Command="NewRibbonButtonCommand"
Image16by16="/_layouts/images/FILMSTRP.GIF"
Image32by32="/_layouts/images/PPEOPLE.GIF"
LabelText="New Button"
TemplateAlias="o2" />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="NewRibbonButtonCommand"
CommandScript="javascript:alert('This is a new button!');" />
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
</Elements>

// Image16by16 and Image32by32 are part of SharePoint 2010

Removing Button:



<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<HideCustomAction Id="RemoveRibbonButton"
Location="CommandUI.Ribbon.Library.Actions.ConnectToClient">
</HideCustomAction>
</Elements>

Technorati Tags: ,

Customizing and Deploying Ribbon in SharePoint 2010

*** Please view the disclaimer before you proceed ***

Introduction: You might have seen in the sneak peek and beta screens of Office 2010 the new Ribbon pattern / interface / control. This post would give details about how to customize and deploy the same using Windows Power Shell.

How to: A sample feature could resemble the following:

<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="FeatureId"
Title="Name of the Feature"
Description="Description of the Feature."
Version="1.0.0.0"
Scope="Web"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="manifest.xml" />
</ElementManifests>
</Feature>

To deploy and enable it use the following commands:

Install-SPFeature FeatureId Enable-SPFeature FeatureId -Url http://server/site/subsite


Technorati Tags: ,

SharePoint Products and Technologies: 2010 (Tech Preview) Developer Documentation

Here is the link. It has got the Reference Document help file and how to customize the new ribbon control.

Help file contains details of lot of new web controls that you might want to see when compared with MOSS 2007.

Monday, July 13, 2009

SharePoint 2010 – Preliminary System Requirements - Getting Ready

Gear up for the SharePoint 2010 now. You might want to check the following and take advantage of the forth coming SharePoint 2010 Services.

Hardware:

    • Plan for 32bit to 64bit upgrade. SP 2010 has 64bit flavor only.
    • SP 2010 needs SQL 2K8 or SQL 2K5 running on 64 bit. Which means, you might want to considering upgrading your SQL box too.
    • SP 2010 will need Windows 2008 Server or above to run.
    • Make sure your development environment is also upgraded to 64bit.

Service Packs:

    • If you are planning to upgrade from MOSS 2007 or WSS 3.0, first deploy your existing environment with SP2 and then upgrade to SP 2010.
    • Run the Upgrade Checker Tool that’s included in SP2 which might bring upfront notice of possible issues during or upon upgrade.

Development:

    • Consider migrating to Visual Studio 2010 (pretty good migration and new tools available)
    • Watch for deprecated API’s
    • New deployment and packaging available with VS 2010 coming along.
    • Learn LINQ, entity models and Silverlight since these are supported in SP 2010.

Browser Compatibility:

    • IE > 6.0 is a mandate, which means you cannot use IE 6.0.
    • Fire Fox 3.x is supported.
Technorati Tags:

SharePoint 2010

Disclaimer:

Hi All,

Very soon I will start blogging about SharePoint 2010 a.k.a SharePoint Services “14”. Well since we are still talking about the beta version coming down during October this year, what ever is written in the blog might change substantially prior to the final commercial release. Also you cannot test them until you have either final product or beta or any prior tech preview releases (if any) that Microsoft makes. The risks associated with the implementation of my writings are purely users and solely its users decision and discretion in using so.

regards,
Srini Sistla

SharePoint 2010 Sneak Peek

Here is the link to the SharePoint 2010 Sneak Peek. Cant wait longer to get hands on :-)... Waiting to see if I can get the tech preview.

Friday, July 10, 2009

SilverLight 3.0 Released

Today SilverLight 3.0 and Microsoft Expression 3.0 released. Details are here.

What’s new in SilverLight 3.0 are here.

Technorati Tags:

Thursday, July 9, 2009

RSS / Atom Aggregator WebPart - Syndication using WCF

Preface: In my previous post, I wrote about the RSS Aggregator Webpart. That version of code used XMLDom model. However, in .NET 3.5 we have syndication classes available and you can see how reading RSS / Atom feeds have become so easy. This supports Atom 1.0 and RSS 2.0 versions.

Since the process is same, you can pass multiple feed url’s and make it aggregator too.

Assembly Reference: System.ServiceModel.Syndication

Solution:

public void GetSyndication(string url)
{
SyndicationFeed feed = SyndicationFeed.Load(XmlReader.Create(url));
if (null != feed)
{
foreach (SyndicationItem item in feed.Items)
{
//Link to the Post - item.Links[0].Uri.AbsoluteUri.ToString()
//Title of the Post - item.Title.Text
//Description - item.Summary.Text
}
}
}

Most of the time, you will end up querying either of Atom / RSS formats and you never know which one is the input. So, I kind of had a check point to validate the input formats. If one of the conversion fails, its obviously the other. Well here is the full code.


Your entry point would be GetSyndicationFeed Method if you dont know what's the incoming feed. However, if you know the feed type then you can directly call either the GetRSSFeedString method or GetAtomFeedString method directly.

public string GetSyndicationFeed(string url, string type)
{
if (string.IsNullOrEmpty(url)) return string.Empty;

string ret = string.Empty;
switch (type.ToLower())
{
case "rss":
ret= GetRSSFeedString(url);
break;
case "atom":
ret= GetAtomFeedString(url);
break;
case "": // Acts as a validator
try {
Rss20FeedFormatter rss = new Rss20FeedFormatter();
rss.ReadFrom(XmlReader.Create(url));
ret= GetRSSFeedString(url);
}
catch (XmlException exml){
ret= GetAtomFeedString(url);
}
break;
}
return ret;
}

public string GetRSSFeedString(string url)
{
StringBuilder sb = new StringBuilder();
Rss20FeedFormatter rss = new Rss20FeedFormatter();

try
{
rss.ReadFrom(XmlReader.Create(url));
}
catch (XmlException exml)
{
// Log it.
}

if (null == rss.Feed) return string.Empty;

foreach (SyndicationItem item in rss.Feed.Items)
{
// item.Links[0].Uri.AbsoluteUri.ToString() // - URL link to the post
// item.Summary.Text.ToString() // - Description or Summary of the post
// item.Title.Text // - Title of the post
}

return sb.ToString();
}

public string GetAtomFeedString(string url)
{
StringBuilder sb = new StringBuilder();
Atom10FeedFormatter atom = new Atom10FeedFormatter();

try
{
atom.ReadFrom(XmlReader.Create(url));
}
catch (XmlException exml)
{
// Log it.
}

if (null == atom.Feed) return string.Empty;

foreach (SyndicationItem item in atom.Feed.Items)
{
// item.Links[4].Uri.AbsoluteUri.ToString() // - URL link to the post
// ((System.ServiceModel.Syndication.TextSyndicationContent)(item.Content)).Text // - Description or Summary of the post
// item.Title.Text // - Title of the post
}

return sb.ToString();
}

Technorati Tags: ,,,,

Wednesday, July 8, 2009

Scheduling a SharePoint Backup

Scenario: Unfortunately as in the previous version, MOSS 2007 also doesn't have a tool for scheduling backups.

Solution: Command-Line backup tools – The stsadm.exe enables sharepoint admins to backup site collections using the command line and makes it easier to restore site collection (or a site).

Usage:
stsadm –o backup –url <url> –filename <filename> [-override]

for example:

stsadm –o backup –url http://myserver/sites/ –filename c:\mybackups\


Catastrophic backup: The stsadm utility now lets you do a full SP backup as you would with a CA Page.


To issue a full or differential backup use the format

stsadm –o backup –directory <unc path> –backupmethod <full | differential> [-item<created path from tree>] [-%<int between 1 and 100>] [-backupthreads<int between 1 and 10>] [-showtree] [-quite]


for example: (to back up entire SP Farm)

stsadm –o backup – directly \\backups\sharepoint –backupmethod full 


Technorati Tags: ,

SharePoint Versions and Licenses

Currently in use in market (not including the previous versions):

Windows SharePoint Services 3.0 – Windows Server CAL or Windows External Connector

Microsoft Office SharePoint Server 2007 Standard – Windows CAL + MOSS Std CAL or Core CAL

Microsoft Office SharePoint Server 2007 Enterprise – Windows CAL + MOSS Std CAL or Core CAL + MOSS Ent CAL or eCAL

Microsoft Office SharePoint Server 2007 for Internet Sites – Windows External Connector + MOSS for Internet Sites (no CALs)

Technorati Tags: ,

Interesting Fact

Certain files in the SharePoint installation folders contain OWS or STS. These stand for Office Web Server and SharePoint Team Services respectively. You also might want to know what VTI stands for as in VTI_BIN. It’s Vermeer Technologies Inc., which was acquired by Microsoft. Vermeer was the original developer of FrontPage.

Tuesday, July 7, 2009

Programmatically Get SPList Attachments

Here is the code snippet to get the Attachments of a given SPList. You can modify the code to return a collection instead.

public void GetListAttachments(string site, string listName)
{
//StringBuilder sAttNames = new StringBuilder();
using (SPSite oSite = new SPSite(site))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
SPList oList = oWeb.Lists[listName];

SPListItemCollection oListItems = oList.Items;
foreach (SPListItem item in oListItems)
{
SPAttachmentCollection collAttachments = item.Attachments;

if (collAttachments.Count <= 0) return string.Empty;

foreach (var attachment in collAttachments)
{
//sAttNames.Append(attachment.ToString());
}
}
}
}
//return sAttNames.ToString();
}


Monday, July 6, 2009

Programmatically getting SharePoint Site Columns

Here is a simple code snippet of how to get all the available Site Columns under a given site.


public string GetSiteColumns(string site)
{
string sRet = string.Empty;
using (SPSite oSPSite = new SPSite(site))
{
using (SPWeb oSPWeb = oSPSite.OpenWeb())
{
foreach (SPField field in oSPWeb.Fields)
{
if(null == field) return null;

//if(field.Group.ToLower() == "srini")
//{
sRet += field.Title.ToString() + ",";
//}
}
}
}
return sRet;
}

SharePoint Site Columns – an Introduction

Scenario: We would like to ‘re-use’ functionalities as much as we can every where. So why not a column that can be reused in every list or on a list i want in specific?

Introduction: Site Columns are ‘meta-data fields’ that you can create and then use them any where you want under any list.

How To: You can create a site column by accessing the page under Site Settings > Site Columns or from the page ‘_layouts/mngfield.aspx’.

Now, you can create the Column and choose type that are available under the New Site Column creation wizard. Also, you can specify to add it under a specific group or create a new group on the fly.

Once you create the column, it is now accessible from any list when you select the option ‘Add from existing site columns’ option.

Interesting: Ok! the beauty of this is… when you update the Site Column values, the column values on your inherited list are automatically updated (default is ‘Auto Yes’). Well, when you delete the Site Column… the inherited list will not lose any data nor the column by itself.

You see what’s happening? Guess why? :-)

Asynchronous Pages in ASP.NET 2.0

Scenario: When ASP.NET receives a page request, it is basically a thread from the thread pool and then considered as a request thread. To understand it simply, consider that the life cycle is Synchronous. Any intermediate Async process is considered as breaking the line of process since Async must run on a separate thread from there onwards. Situations some time tend us to use some process and we will be immediately thrown with the error below.

Error: “Asynchronous operations are not allowed in this context. Page starting an asynchronous operation has to have the Async attribute set to true and an asynchronous operation can only be started on a page prior to PreRenderComplete event”

Support: ASP.NET 1.1 version does not support it OOB but it has a back door entry to do it.

However in ASP.NET 2.0, its a very simple attribute setting on the page directive.

<% Page Async=”true”…...


Consider that the situation further demands that you need to set it on run time and not on design time on page.



So, one has to subscribe to the below event and do the rest of the magic.



AddOnPreRenderCompleteAsync (
new BeginEventHandler(MyBeginMethod),
new EndEventHandler (MyEndMethod)
);


for more detailed information, view this blog

Saturday, July 4, 2009

Merging multiple SPList and binding to SPGridView

Scenario: Many instances it so happens that we have to read multiple list and merge them together and then bind the merge list to SPGridView. Here is one example of how to implement it. This is a vanilla code which works great. But its at your discretion that you can further simplify and refactor it.

Implentation:

I used 2 classes here. Again use your own ideas how you want to make it more better.
Before we start, I created 2 custom list (1 with name 'Srini Test' and other with 'New List') with columns added as 'URL' and 'Description' along with 'Title' (default OOB).

Util Class:
---------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data;
using System.Web;
using Microsoft.SharePoint;
namespace BlogIt
{
public class Util
{
public DataTable GetDataTableFromList(string site, string web, string listname)
{
DataTable dt = null;
using(SPSite oSPSite = new SPSite(site))
{
using(SPWeb oSPWeb = oSPSite.OpenWeb())
{
SPList oList = (SPList)oSPWeb.Lists[listname];
dt = oList.Items.GetDataTable();
}
}
return dt;
}
}
}

---------------------------------------------------------------------------
Webpart Class:
---------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
namespace BlogIt
{
public partial class _Default : System.Web.UI.Page
{
Util oUtil = new Util();
SPGridView oSPGridView = new SPGridView();
protected override void OnInit(EventArgs e)
{
oSPGridView.ID = "_spgv1";
oSPGridView.AutoGenerateColumns = false;
BuildGridColumns();
base.OnInit(e);
}
private void BuildGridColumns()
{
BoundField bfTitle = new BoundField();
bfTitle.HeaderText = "Title";
bfTitle.DataField = "Title";
oSPGridView.Columns.Add(bfTitle);
BoundField bfURL = new BoundField();
bfURL.HeaderText = "URL";
bfURL.DataField = "URL";
oSPGridView.Columns.Add(bfURL);
}
protected override void CreateChildControls()
{
this.Controls.Add(oSPGridView);
base.CreateChildControls();
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable oDt1 = oUtil.GetDataTableFromList("http://localhost:81/", string.Empty, "Srini Test");
DataTable oDt2 = oUtil.GetDataTableFromList("http://localhost:81/", string.Empty, "New List");
oDt1.Merge(oDt2);
oSPGridView.DataSource = oDt1;
oSPGridView.DataBind();
}
public override void VerifyRenderingInServerForm(Control control)
{

}
}
}

---------------------------------------------------------------------------

Friday, July 3, 2009

Stsadm command for Switching Authentication Mode - Access Denied Issue

Last week we used the below command and encountered an issue that the conversion was unsuccessful. However, on CA it was showing that it converted correctly.

STSADM -o authentication -url -type forms -membershipprovider -roleManager

Now, when we access the site it was giving AccessDenied error.

After our analysis, we figured out that the Database was not correctly updated with the job.

So we did 2 steps:

#1: From CA, we changed the authentication mode to Windows - Successful. We changed again to Forms - Failed.
#2: Now we are our fav command : ststadm -o execadmsvcjobs

Success. Now the mode is correctly changed as the job status is complete.

Thursday, July 2, 2009

Using Disposable Objects (SharePoint Best Practices)

Question:
Why do we need to dispose objects we create?
Most often we tend to write Unmanaged code inside managed code. Managed Objects created from such Managed classes as SPSite and SPWeb
has very little to do with the unmanaged code sitting inside their boundary. Now, when you compare this size of the managed part is considerably
lesser than that of the unmanaged part, GC would ignore mostly and doesnt clear the objects created underneath. This results in memory leaks, your application performs slow, and you have a big laundry list of items to complain etc etc and etc.

Solution:
3 suggested best practices are as below:

#1. Use Dispose or Close Methods - Technically both are same, just that Dispose again calls Close internally.
#2. Using Clause - Automatic Dispose
#3. Use Try, Catch and Finally Block - Manual Force - Best method as I feel, since it gives you the power of catching the exceptions if any.


Examples:


"using Clause"
 
String str;

using(SPSite oSPsite = new SPSite("http://server"))
{
using(SPWeb oSPWeb = oSPSite.OpenWeb())
{
str = oSPWeb.Title;
str = oSPWeb.Url;
}
}

In the above example though SPSite is the parent of SPWeb and takes care of disposing the SPWeb object (incase you havent auto or forced it), its good to also have the using clause for the SPWeb object too.


"Using Try, Catch and Finally Blocks"
 
String str;
SPSite oSPSite = null;
SPWeb oSPWeb = null;

try
{
oSPSite = new SPSite("http://server");
oSPWeb = oSPSite.OpenWeb(..);

str = oSPWeb.Title;
}
catch(Exception e)
{
//Handle exception, log exception, etc. // NEVER EVER LEAVE THIS BLOCK EMPTY.
}
finally
{
if (oSPWeb != null) // GOOD PRACTICE TO CHECK IF OBJECT IS NOT NULL BEFORE DISPOSING
oSPWeb.Dispose();

if (oSPSite != null) // GOOD PRACTICE TO CHECK IF OBJECT IS NOT NULL BEFORE DISPOSING
oSPSite.Dispose();
}



for more information on Best Practices, follow this link here.