Thursday, December 30, 2010

Introduction to Webparts in Sharepoint

About WebParts


Microsoft first introduced Web Parts in Windows SharePoint Services (WSS) 2.0. Information workers and developers quickly adopted Web Parts because they enable end users to modify the content, appearance, and behavior of pages through a browser.
Not only could users easily modify the content and experience with the browser, but they could also modify pages for just their own experience, rather everyone ’ s shared experience. Web Parts became so popular that the ASP.NET team decided to add a Web Part Framework to ASP.NET 2.0. The ASP.NET 2.0 implementation is different from the WSS 2.0 implementation in that ASP.NET 2.0 adds a new component to the page: the WebPartManager . The WebPartManager control is responsible for managing all aspects of Web Parts on the page. It knows what Web Parts are allowed on the page, what Web Parts are already on the page and which Web Part zones they are in, any connections that have been established between two Web Parts, as well as the personalization data for each Web Part. Personalization data contains all the settings, or values, set on the public properties, for a Web Part. This is very different from the WSS 2.0 Web Part Framework in that each Web Part maintained its own connection and personalization information and Web Part zones managed which Web Parts were in each zone.

What happens when a Web Part is added to a Web Part zone?


SharePoint adds some XML to the Web Part zone that contains information about the assembly
containing the Web Part and the Web Part class itself. This XML also contains the values of the public
properties on the Web Part class.

<WebPart xmlns=”http://schemas.microsoft.com/WebPart/v2” xmlns:iwp=”http://schemas.microsoft.com/WebPart/v2/Image”>
<Assembly> Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c </Assembly>
<TypeName> Microsoft.SharePoint.WebPartPages.ImageWebPart </TypeName>
<FrameType> None </FrameType>
<Title> Watch My Gears Run </Title>
<iwp:ImageLink> /_layouts/images/GEARS_AN.GIF </iwp:ImageLink>
</WebPart>

This XML, shown in above, is then stored as personalization information for a specific user (if the personalization scope is set to User) or for all users who access the page (if the personalization scope is set to Shared) depending on the mode of the page. The next time a page is requested, SharePoint loads the personalization information for the Web Part, which tells it which class to load from which assembly and the values of the public properties to set on that class. The Web Part is then loaded within the ASP.NET 2.0 page life cycle, which generates the rendered HTML output.

WebParts Base Classes


Microsoft has provided two base classes from which developer can create custom web parts
ASP.NET 2.0 — System.Web.UI.WebControls.WebParts.WebPart
WSS / SharePoint 3.0 — Microsoft.SharePoint.WebPartPages.WebPart

Why to use ASP.Net web part class not SharePoint web part class?


When creating a new Web Part, Microsoft ’ s recommendation is to always create ASP.NET 2.0 Web Parts instead of SharePoint - specific Web Parts. Web Parts created from ASP.Net web part class (System.Web.UI.WebControls.WebParts.WebPart) are fully supported in Windows SharePoint Services, and can be used not only in ASP.NET applications but also in Windows SharePoint Services too. The SharePoint web part class was designed specifically for SharePoint sites, and Web Parts that inherit from this class can be used only in Windows SharePoint Services sites.
When creating new Web Parts, you have the option of creating Web Parts that inherit from System.Web.UI.WebControls.WebParts.WebPart (recommended) or Microsoft.SharePoint.WebPartPages.WebPart. The Windows SharePoint Services WebPart class exists primarily for the purpose of backward compatibility (Web Parts written for Windows SharePoint Services 2.0 continue to work in Windows SharePoint Services 3.0 without modification).

References
Professional SharePoint 2007 Web Content Management Development
Webpart Class

Friday, October 22, 2010

Break the variation in Sharepoint

Most of the Sharepoint Developers/Content Editors facing below problem in Variation feature of MOSS.
Publishing a page in the variation source site overwrites all contents in the target site

If below variation settings are ON.

  • Automatically create site and page variations

  • Recreate a new target page when the source page is republished.

  • Update Web Part changes to target pages when variation source page update is propagated.


Case is like this,

First time when we create page XYZ in source variation(English) this page will automatically get created on target variation site(French). Then content editor add some content to this page and publish it. That contents will also get reflected to target page but that is not in French because Sharepoint will not do the task of content translation. This time content editor edit content on French site and publish it.

Now everything is working fine till new change.

After some days there is one minor change in English site. Hence content editor do that change and publish it. Now disaster came into his life.

All the contents of French page get overwritten by English page.

Now we will talk about the workarounds.

1: Temporary solution
Go to the target page version history and restore current published major version.

2: Permanent solution
Attempt this once page created on first time. Delete target(French) page when it automatically created. Create new page with same name in target(French). This will break variation link between source and variation page. Add/Update the content and publish it.

By doing this you will see an error in Variation log

An error occurred during page variation creation. A page already exists at the target location:

Don't worry...! This error is coming because we breaked variation link. This will happen on every update on source page.

Cheers! Now enjoy content editing.

Saturday, August 21, 2010

Benefits of detaching publishing page from page layout

In the publishing feature of Sharepoint every page must be derived from the page layout. This page layout actually decide the look and feel plus contents of the page, so if u use one layout more than a page then it is difficult to manage the look and feel because if u make change in page layout then this changes are automatically reflected on all the pages which using this page layout.
Sharepoint designer has given one nice functionality to detach the page from it's layout. By detaching page from it's layout, page got a following benefits.

  • All the content fields and page fields can be used on the page.

  • Use any designs templates to the page,this will not affect to other pages.

  • Getting advantage of using DataView, FormView webparts etc.


That's all here.

Tuesday, February 9, 2010

List Tree View in Sharepoint


In one of our project there are more than 100 lists and every list is having nested folders as well as many items. My client don't want to dig the list to see all the nested folder inside it. So we decided to provide him the Tree View control which will show all the lists inside site and also show all the items/data inside a list and he can easily navigate to particular list/folder and item.

First we will show all the items/nested folder in TreeView

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

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Nishnat.ListTreeView
{
public class ListItems : WebControl
{
public string ListName { get; set; }

protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// render the control
base.RenderContents(writer);
}

protected override void CreateChildControls()
{
base.CreateChildControls();

using (SPSite ospSite = new SPSite("http://localhost:7777/"))
{
using (SPWeb web = ospSite.RootWeb)
{
try
{
SPList list = web.Lists[ListName];

SPFolder rootFolder = list.RootFolder;
TreeView listTree = new TreeView();
listTree.ShowLines = true;
listTree.ExpandDepth = 0;

TreeNode rootNode = new TreeNode();

//Bind tree
MakeTreee(rootFolder, rootNode);

// add the root node to tree view
listTree.Nodes.Add(rootNode);
this.Controls.Add(listTree);
}
catch(Exception ex)
{
throw ex;
}
}
}
}

private void MakeTreee(SPFolder rootFolder, TreeNode rootNode)
{
SPQuery query = new SPQuery();
query.Folder = rootFolder;
SPWeb web = rootFolder.ParentWeb;
SPListItemCollection listColl = web.Lists[rootFolder.ParentListId].GetItems(query);

foreach (SPListItem subitem in listColl)
{
if (subitem.Folder != null) //Is folder
{
TreeNode childNode = new TreeNode(subitem.Folder.Name,subitem.ID.ToString(), "_layouts/images/folder.gif", subitem.Folder.ServerRelativeUrl, "");
rootNode.ChildNodes.Add(childNode);
MakeTreee(subitem.Folder, childNode);
}
else
{
string displayURL = GetDisplayUrl(subitem);

TreeNode childNode = new TreeNode(subitem.Name, subitem.Name, "", displayURL, "");
rootNode.ChildNodes.Add(childNode);
}
}
}

private static string GetDisplayUrl(SPListItem item)
{
SPList list = item.ParentList;
SPWeb web = list.ParentWeb;

string dispUrl = item.ContentType.DisplayFormUrl;
//dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (dispUrl == "")
dispUrl = list.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;

bool isLayouts = dispUrl.StartsWith("_layouts/", StringComparison.CurrentCultureIgnoreCase);
dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (isLayouts)
dispUrl = String.Format("{0}&amp;List={1}", dispUrl, SPEncode.UrlEncode(list.ID + ""));
return dispUrl;
}
}
}


Second we will show all the Lists/items/nested folder in TreeView


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

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Nishnat.ListTreeView
{
public class AllListsWithItems : WebControl
{
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// render the control
base.RenderContents(writer);
}

protected override void CreateChildControls()
{
base.CreateChildControls();

using (SPSite ospSite = new SPSite("http://localhost:7777/"))
{
using (SPWeb web = ospSite.RootWeb)
{
try
{
TreeView listTree = new TreeView();
listTree.ShowLines = true;
listTree.ExpandDepth = 0;

SPListCollection listAll = web.Lists;

foreach (SPList list in listAll)
{
SPFolder rootFolder = list.RootFolder;

TreeNode rootNode = new TreeNode(list.Title,list.ID.ToString(),list.ImageUrl,list.ParentWebUrl,"");

//Bind tree
MakeTreee(rootFolder, rootNode);

// add the root node to tree view
listTree.Nodes.Add(rootNode);
this.Controls.Add(listTree);
}
}
catch(Exception ex)
{
throw ex;
}
}
}
}

private void MakeTreee(SPFolder rootFolder, TreeNode rootNode)
{
SPQuery query = new SPQuery();
query.Folder = rootFolder;
SPWeb web = rootFolder.ParentWeb;
SPListItemCollection listColl = web.Lists[rootFolder.ParentListId].GetItems(query);

foreach (SPListItem subitem in listColl)
{
if (subitem.Folder != null) //Is folder
{
TreeNode childNode = new TreeNode(subitem.Folder.Name,subitem.ID.ToString(), "_layouts/images/folder.gif", subitem.Folder.ServerRelativeUrl, "");
rootNode.ChildNodes.Add(childNode);
MakeTreee(subitem.Folder, childNode);
}
else
{
string displayURL = GetDisplayUrl(subitem);

TreeNode childNode = new TreeNode(subitem.Name, subitem.Name, "", displayURL, "");
rootNode.ChildNodes.Add(childNode);
}
}
}

private static string GetDisplayUrl(SPListItem item)
{
SPList list = item.ParentList;
SPWeb web = list.ParentWeb;

string dispUrl = item.ContentType.DisplayFormUrl;
//dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (dispUrl == "")
dispUrl = list.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url;

bool isLayouts = dispUrl.StartsWith("_layouts/", StringComparison.CurrentCultureIgnoreCase);
dispUrl = String.Format("{0}/{1}?ID={2}", web, dispUrl, item.ID);

if (isLayouts)
dispUrl = String.Format("{0}&amp;List={1}", dispUrl, SPEncode.UrlEncode(list.ID + ""));
return dispUrl;
}
}
}


* Add assembly into GAC and Bin application

* Register the control on the page


<@ Register Tagprefix="Nishnat" Namespace="Nishnat.ListTreeView" Assembly="Nishnat.ListTreeView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=57c7737278844f55">


* Now Use it on the page

<Nishnat:ListItems Id="listItems" runat="server" ListName="Books">
</Nishnat:ListItems>
<Nishnat:AllListsWithItems Id="AllListsWithItems" runat="server">
</Nishnat:AllListsWithItems>