Thursday, July 7, 2011

Deleting a Web Part from a page

using System;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;

namespace SampleCode
{
class DeleteWebPart
{
static void Main()
{
ClientContext oClientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
File oFile = oClientContext.Web.GetFileByServerRelativeUrl("/sites/MySiteCollection/SitePages/Home.aspx ");
LimitedWebPartManager limitedWebPartManager = oFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

oClientContext.Load(limitedWebPartManager.WebParts);

oClientContext.ExecuteQuery();

if (limitedWebPartManager.WebParts.Count == 0)
{
throw new Exception("No Web Parts to delete.");
}

WebPartDefinition webPartDefinition = limitedWebPartManager.WebParts[0];

webPartDefinition.DeleteWebPart();

oClientContext.ExecuteQuery();
}
}
}

Adding a Web Part to a page

using System;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;

namespace SampleCode
{
class AddWebPart
{
static void Main()
{
ClientContext oClientContext = new ClientContext("http://MyServer/sites/MySiteCollection");
File oFile = oClientContext.Web.GetFileByServerRelativeUrl("Default.aspx");
LimitedWebPartManager limitedWebPartManager = oFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

string xmlWebPart = "" +
" " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
" xmlns=\"http://schemas.microsoft.com/WebPart/v2\">" +
"My Web PartDefault" +
"Use for formatted text, tables, and images." +
"true0" +
"Normaltrue" +
"truetrue" +
"truetrue" +
"truetrue" +
"ModelessDefault" +
"Cannot import this Web Part." +
"/_layouts/images/mscontl.gif" +
"Microsoft.SharePoint, Version=13.0.0.0, Culture=neutral, " +
"PublicKeyToken=94de0004b6e3fcc5
" +
"Microsoft.SharePoint.WebPartPages.ContentEditorWebPart" +
"" +
"" +
" 
And this is a second paragraph.]]>" +
"";

WebPartDefinition oWebPartDefinition = limitedWebPartManager.ImportWebPart(xmlWebPart);

limitedWebPartManager.AddWebPart(oWebPartDefinition.WebPart, "Left", 1);

oClientContext.ExecuteQuery();
}
}
}

Updating the title of a Web Part

using System; using Microsoft.SharePoint.Client; using Microsoft.SharePoint.Client.WebParts;  namespace SampleCode {     class UpdateWebPartTitle     {         static void Main()         {             ClientContext oClientContext = new ClientContext("http://MyServer/sites/MySiteCollection");             File oFile = oClientContext.Web.GetFileByServerRelativeUrl("Default.aspx");             LimitedWebPartManager limitedWebPartManager = oFile.GetLimitedWebPartManager(PersonalizationScope.Shared);              oClientContext.Load(limitedWebPartManager.WebParts,                 wps => wps.Include(                 wp => wp.WebPart.Title));              oClientContext.ExecuteQuery();              if (limitedWebPartManager.WebParts.Count == 0)             {                 throw new Exception("No Web Parts on this page.");             }              WebPartDefinition oWebPartDefinition = limitedWebPartManager.WebParts[1];             WebPart oWebPart = oWebPartDefinition.WebPart;             oWebPart.Title = "My New Web Part Title";              oWebPartDefinition.SaveWebPartChanges();              oClientContext.ExecuteQuery();          }     } }

Wednesday, July 6, 2011

SharePoint 2010 Best Practices

While developing custom solutions based on SharePoint, we need to strictly adhere certain best practices that are proposed by Microsoft SharePoint team.

1.1 Usage of SharePoint Object Model

Most of the SharePoint developers use SharePoint API’s like SPSite, SPWeb, SPList objects extensively. There will be a serious performance hits and memory leaks, when those objects are not properly used.

In most of the cases the code will work well, but whenever the data get heavy, there should be a huge performance hits, because of not properly usage of SharePoint API’s.

This section will elaborate about the best practices on how to use SharePoint API’s especially when we use objects like SPSite, SPWeb, SPList, etc., and also some coding practices.

A good or best practice we need to follow is whenever we use SPSite, SPWeb objects, we need to properly dispose those objects; otherwise, there will be a huge performance impact.

public void SPSiteAndSPWebProperlyDisposeUsing ()

{

using (SPSite site = new SPSite(http://moss))

{

using (SPWeb web = site.OpenWeb ())

{

//do your logic

}

}

}


One thing we need to remember that, we when we create an instance of SPSite or SPWeb using SPControl or SPContext class, do not dispose the instance of SPSite or SPWeb objects.

For example

SPSite site = SPControl.GetContextSite (Context);

site.Dispose (); //Do not do this

SPWeb web = SPControl.GetContextWeb (Context);

web.Dispose (); //Do not do this

SPSite site = SPContext.Current.Site;

site.Dispose (); //do not do this

SPWeb web = SPContext.Current.Web;

web.Dispose (); //do not do this


Note: We do not need to dispose the SPWeb instance when using SPSite.RootWeb and SPSite.ParentWeb properties

There is a tool called “SPDisposeCheck”, which will guide us to check whether all the SPSite and SPWeb instances are properly disposed. This tool will check the assembly and reports the developer how many instances are not disposed properly. Also we can add this utility in our Visual Studio environment.

There are several other SharePoint objects that are required to be disposed properly. For more details refer to the reference section links.

1.2 Interacting with large SharePoint list using SharePoint object model

When we interacting with list containing huge number of items using SharePoint OM, we may need to consider the following best practices

Case # 1: Getting the list items count

Using SharePoint OM, we can get the list item count like

int count = SPContext.Current.List.Items.count; //Do not use


The above code snippet is valid to get the count, if the list is tiny. At the same time, if the list contains huge items, there will be a performance degrade with above code. Since List.Items.Count retrieve all the list items in the memory and find out the total count.

In order to avoid this, we can use the following code to retrieve the total items count even though the list contains huge items

int count = SPContext.Current.List.ItemCount; //Use this code


Here, the ItemCount is the metadata of a list and will be created whenever we create a new instance of a list.

Case # 2: Iterating the list items to display

We can iterate through the list items using SharePoint OM as follows:

SPList list = SPContext.Current.List;

for(int i=0; i

{

SPListItem item = list.Items[i];

htmlWriter.Write(item[“Title”]);

}


The above code snippet is incorrect way to access the list items, because for each loop, there is a new instance of SPListItemCollection gets created when accessing Items property. Also, the Items property will not be cached and therefore request the database for each loop.

The correct way to do it:

SPListItemCollection itemsCol = SPContext.Current.List.Items;

for(int i=0; i

{

SPListItem item = itemsCol[i];

htmlWriter.Write(item[“Title”]);

}


Case # 3: Retrieve required items we need - SPQuery and SPView SharePoint OM

Instead of retrieving all the items from the list, we can retrieve only the required items from list.

For this purpose, we can use SPQuery and SPView objects

Limiting the number of returned rows:-

Using SPQuery instance, we can limit the number of rows to be retrieved from the list, so as to avoid all the items from the list.

SPQuery query = new SPQuery();

query.RowLimit = 100; //Here, we are limiting the items to be returned only 100


Limiting the number the columns to be retrieved:-

Let’s say, a SharePoint list contains 100 columns, and it is not a good practice to retrieve columns that are not necessary. For this, we have two approaches to limit the retrieved columns

Using SPView instance:-

SPQuery query = new SPQuery (SPContext.Current.CurrentView.View);


Using SPQuery.ViewFields property:-

SPQuery query = new SPQuery ();

Query.ViewFields = “”;


In both cases, the select statement will have only the required columns.

Case # 4: Retrieving list items using PortalSiteMapProvider

The PortalSiteMapProvider is one of the ways to retrieve list items from SharePoint very efficiently. It is a MOSS feature and provides an automatic caching mechanism to cache the list items.

PortalSiteMapProvider class has a method namely GetCachedListItemsByQuery takes the instance of SPQuery as parameter for retrieving the list items.

Prior to retrieving the list items, it checks whether the list items is available in cache, if so it retrieves from cache, otherwise, it retrieves from database and put it in cache for next retrieval.

The advantage of this method is it doesn’t have to retrieve the list items from database every time and hence improve the performance.

There are some limitations of using this method as well

· Do not use this method to retrieve the list items, which are not static data, because it continually checks for cache, if not retrieves the items from database and again put it in cache. There are some performance degrade in terms of checking and writing back to cache

· Default memory size for the cache is 100 MB, but we can increase the size. The increased size has to be taken from the shared memory of the application pool and there by affect the performance of the other applications

· We cannot use the PortalSiteMapProvider class in applications like Windows Forms

Following shows the code snippet on how to use the PortalSiteMapProvider efficiently

SPWeb web = SPControl.GetContextWeb (HttpContext.Current);

SPQuery query = new SPQuery ();

query.Query = "

Hotel";

PortalSiteMapProvider portal = PortalSiteMapProvider.WebSiteMapProvider;

PortalWebSiteMapNode portalNode = portal.FindSiteMapNode (web.ServerRelativeUrl) as PortalWebSiteMapNode;

SiteMapNodeCollection portalItems = portal.GetCachedListItemsByQuery (pNode, "myListName_NotID", query, web);

foreach (PortalListItemSiteMapNode item in portalItems)

{

// Do something with each match.

}


1.3 Caching Objects for better Performance

Caching is one of the techniques in .NET world to increase the performance by reducing the roundtrips to backend database. In SharePoint also, we can leverage the .NET class (System.Web.Caching.Cache) to cache the SharePoint objects.

Caching helps us to reduce the usage of memory and increase the overall system performance. But, many objects are not “thread safe” and caching those objects can lead to application crashes and unexpected or unrelated use errors.

There are few considerations we need to take care when caching SharePoint objects.

Caching SharePoint objects that are not thread safe:

When we trying to get list items from a SharePoint list using SPQuery object and results are stored in SPListItemCollections objects, it is a good practice to cache the SPListItemCollections object.

But, the object SPListItemCollections will contain an embedded SPWeb object, which is not thread safe and should not be cached. When it is cached, there might be some unexpected errors.

So, don’t cache the objects which are thread unsafe.

Not using Thread Synchronization:

We need to know understand that the IIS is a multi-thread environment and many users can access the site simultaneously. We need to write code that target for multi-thread environment

public void CacheItems ()

{

SPListItemCollections listItems;

listItems = (SPListItemCollections) Cache [“ListItemsData”];

if (listItems == null)

{

listItems = getData ();

Cache.Add (“ListItemsData”, listItems);

}

}


In the above code snippet, the problem is that if the query to get items takes 10 seconds, there might be a chance that many users can hit the page simultaneously, trying to get the items and update the cache objects at the same time.

Since the same query might run 10, 50 or 100 times, there should be a performance issues and worst case the application may crash because multiple threads are trying to update the same cache objects.

To avoid this scenario, we need to modify the above code snippet as shown below

public void CacheItems ()

{

SPListItemCollections listItems;

lock (this)

{

listItems = (SPListItemCollections) Cache [“ListItemsData”];

if (listItems == null)

{

listItems = getData ();

Cache.Add (“ListItemsData”, listItems);

}

}

}


In the above sample code snippet, lock (this) statement ensures that when a thread is inside lock statement and another thread attempts to enter, it place a lock over that thread until the previous thread leaves the lock statement.

Caching an object which is thread safe:

Always cache the objects, which are “thread safe”. In the above code, SPListItemCollections is not a thread safe object, since SPWeb object is embedded in it, which is thread unsafe.

In order to cache the SPListItemCollections in order to avoid roundtrips to backend database, use DataTable .NET object to cache instead of SPListItemCollections as shown below

public void CacheItems ()

{

DataTable dtItems;

SPListItemCollections listItems;

lock (this)

{

dtItems = (DataTable) Cache [“ListItemsData”];

if (dtItems == null)

{

listItems = getData ();

dtItems = listItems.GetDataTable ();

Cache.Add (“ListItemsData”, dtItems);

}

}

}

1.4 SharePoint naming conventions

1.4.1 URL length

A limitation of SharePoint to be reckoned with is the fact that the total length of a URL in SharePoint may no longer than 260 characters.

It is therefore necessary to keep URL names of sites, libraries and to a lesser extent also lists, as short as possible without the clarity and definition deficit is made.

Clear guidelines help here, so see below for an explanation of naming components of Microsoft Office SharePoint Server 2007.

These guidelines should be known to all those potential sites, libraries and / or lists in Microsoft Office SharePoint Server 2007.

1.4.2 Features

Features need to be uniquely named.

1.4.3 Naming of Items in SharePoint

Lists & libraries

Provide lists and libraries with a short but full name clearly describing the application.

Keep the following guidelines:

· Use plural nouns, optionally combined with an adjective

· Avoid using punctuation in their name

· Do not take the name of the site in the list or library name

· Take only words like Documents, Library List, or when it adds value

· Start each word is capitalized

Templates

Templates Give a short name that describes its full content or function.

This, keep the following guidelines:

· For the filename (filename) exactly the same name but without spaces

· Use singular nouns in

· Avoid using punctuation in their name

· Start each word is capitalized

· Take the name for clarity on the template type (eg Project Site, Project Page, Project or Project Library List)

Good names include:

· Project Library (filename ProjectBibliotheek.stp)

· Timesheet List (filename UrenverantwoordingLijst.stp)

· SharePoint Training Site (filename SharePointTraining.stp)

For example:

Title: Standard

Name: Standaard.master

Description: The default master page with corporate branding

Title: Regional

Name: Regionaal.master

Description: A derivative of the standard master page with regional branding

Title: News Overview

Name: NieuwsOverzicht.aspx

Description: A list of news articles collected from current and underlying sites, webparts area on the right

Title: News Article

Name: NieuwsArtikel.aspx

Description: Standard pre-defined layout for news

Webparts

Give Web a full name that the functionality of the Web completely and unambiguously describes.

This, keep the following guidelines:

· Start each word is capitalized

· Use Pascal case for the file name

· Keep file names as identical as possible to the title, but without spaces and punctuation

Web Applications

Web Applications Provide a name that fully describes the content or function.

This, keep the following guidelines:

· Use the name of the application

· Avoid using punctuation in their name

· Start each word is capitalized

Good names include:

· Intranet Publication

· Partner Portal

· My Sites

Site Collections

Site Collections Give a name that completely describes its content or function.

This, keep the following guidelines:

· The name provides a grouping of the underlying sites

· Avoid using punctuation in their name

· Start each word is capitalized

· Observe the alphabetical sorting of Site Collection inside a web application

Good names include:

· Intranet GB

· Arnhem

· Public Blogs

Sites

Sites Enter a name that fully describes its content or function.

This, keep the following guidelines:

· The name indicates a specific application or part of the Site Collection to

· Avoid using punctuation in their name

· Start each word is capitalized

· Observe the alphabetical sorting of Sites within a Site Collection and menus and such.

Good names include:

· Search

· News

· Personnel Department

· Strategy

· Steve's Blog

Pages

Give titles and contents pages try to file as much as possible to match with the

title.

· This, keep the following guidelines:

· The more keywords in the title the better the result will be

· Avoid using punctuation in their name

Good names include:

· Abstract Social Report

filename: AbstractSociaalJaarverslag.aspx

· Overview of contact regional offices

Filename: Overzichtvancontactgegevensregiokantoren.aspx

Site Columns

Enter a descriptive name that does not overlap in meaning with other columns.

When used for a specific application and / or for a specific type of content, use for grouping of the columns the name of the application and / or content type.

When creating the column is important to the column name in Pascal case with no spaces or punctuation to fill. This cannot be adjusted later.

After creating the column, the column can be adjusted and the correct name to be filled, starting each word with a capital letter.

Good names include:

· Project Status

· Internal name: project status

· Internal Product Registration Code

· Internal name: internal product registration code

Content types

Give a descriptive name given to a logical grouping of Site

Columns usually describes a specific application. When specific to the Content Type, columns are prepared they will be grouped under exactly the same as the name of the Content Type.

This, keep the following guidelines:

· The name indicates a group of Site Columns

· Avoid using punctuation in their name

· Start each word is capitalized

· Observe the alphabetical sorting of Site Collection inside

Good names include:

· Incoming Invoice

· PID

1.4.4 Naming of Content

Titles

Page titles for a number of reasons one of the main components of a web page.

Make sure the title is a substantive description of the page where the most meaningful keywords to find the page are included.

The title is used for indexing and ranking of the page to search the contents of the title usually weighs more heavily than other information on the page.

Also, the title used in the display of search, navigation and other dynamic lists. It is therefore important to be aware that even if the title appears in a different context (eg in a block of related pages) should be more fully descriptive.

Example: Procedure Calling in sick: What to do when you are sick

Hyperlinks

When placing hyperlinks in text, it is important to ensure that the hyperlink itself as fully as possible the contents of the destination page describes.

Do not take "Click here" or "Read More" links but make sure the hyperlink itself describes the target content. Indexing for search as well as mobile browsers make good use of descriptive links.

If the hyperlink text is not like an image or a block of information, it can still define the TITLE attribute of the hyperlink itself can be added.

Navigation block

When placing hyperlinks in navigation blocks, it is important to ensure that the hyperlink itself as fully as possible the contents of the destination page describes in the fewest words.

Please also do not list "Click" on hyperlinks, and no navigation icons.

Nevertheless if necessary to make sure that the TITLE attribute for navigation provides a good description of the hyperlink.

Labeling of elements

It is recommended by a LABEL (FOR attribute) to refer to form element so that

users can use this interface and the machine also "understands" that the label describes the control.

Dictionary: Imagine an application and possibly also a comprehensive dictionary of universal terms and names as they appear in the various applications used to universal terms and names as they appear in the various applications used to be.

2 Deployment

2.1 Versioning

2.2 WSP / Feature structure

2.2.1 General

Group multiple artifacts in one feature.

Note that features are visible in site settings so we do not need a list of 30 ENDK features

Group by functionally (so not technically by artifact)

This way updates can be by functional area, developer is responsible for package.

Ofcourse there have to be ‘general’ packages, grouped by artefact as well
(e.g. master page and visual design)

-but we do not want 40 wsp’s with one feature.

2.2.2 WSP

Separate code from content definitions.

Reason – this allows code to be updated without affecting content (types) definitons

No Farm scoped WSP’s

Since these apply to All web applications on the farm

2.2.3 Feature

No hidden features

Since these are hard to find later and are poorly manageable .

Use feature and solution dependencies.

Make WSP’s dependent on other Wsp’s where needed (note this only applies on first installation, not on uninstall or update!)

No web application scoped featurus - scope features appropriately

Note scope. Site scoped features cannot be dependent on site Collection features

3 Decisions

3.1 GAC of bin

We deploy or code in the GAC.

Reason

· Simplification

· Some code has to be in GAC anyway (workflow, timer job, masterpage).

· No issues with trust level and CAS policy

· No record of injection of security breaches (by having a component in the GAC executing web-injected code exists)

3.2 webparts development in codebehind of via loading usercontrols

We wrap usercontrols in webparts (using visual webpart)

Reason

· Developer productivity (using design view in VS)

· Functionality same as code only webparts

· Ascx has to be deployed separately in SP2007. 2010 uses visual webparts so – no issue there.

3.3 content types via CAML of from code

3.4 site definitions

Refrain from using site definitions!

These are non updateable when content exists. Use features.

4 References

4.1 Dispose patterns of SharePoint APIs

http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx

http://msdn.microsoft.com/en-us/library/bb687949.aspx

http://msdn.microsoft.com/en-us/library/aa973248.aspx

http://blogs.technet.com/stefan_gossner/archive/2008/12/05/disposing-spweb-and-spsite-objects.aspx

http://blogs.msdn.com/rogerla/archive/2008/10/04/updated-spsite-rootweb-dispose-guidance.aspx

Featured Posts

#Linux Commands Unveiled: #date, #uname, #hostname, #hostid, #arch, #nproc

 #Linux Commands Unveiled: #date, #uname, #hostname, #hostid, #arch, #nproc Linux is an open-source operating system that is loved by millio...