Tuesday, December 28, 2010

ERROR: One or more types failed to load.

Let me save someone some time.

So I was trying to run SharePoint Products and Technology Configuration Wizard for MOSS 2007, and during the course, I faced the error message, as seen from the screen dump above, "One or more types failed to load. Please refer to the upgrade log for more details". After alot of research, I came to learn that this was being caused by Office 2010 which was installed on the same machine as MOSS 2007. Therefore, the error went when I uninstalled Office 2010.

Happy holidays ;)

Tuesday, December 14, 2010

How to Scope your SharePoint Projects

The "SharePoint project scope" is all of the things that must be produced to complete a SharePoint project. These 'things' are called deliverables and you need to describe them in depth as early in the SharePoint project as possible, so everyone knows what needs to be produced. Take these 5 Steps to scope your SharePoint projects:

Step 1: Set the Direction

Start off by setting the direction for the SharePoint project. Do you have an agreed SharePoint project Vision, Objectives and Timeframes? Are they specified in depth and has your customer agreed to them? Does everyone in the SharePoint project team truly understand them and why they are important? Only by fixing the SharePoint project direction can you truly fix the SharePoint project scope.

Step 2: Scope Workshops

The best way to get buy-in to your SharePoint project scope is to get all of the relevant stakeholders to help you define it. So get your SharePoint project sponsor, customer and other stakeholders in a room and run a workshop to identify the scope. What you want from them is an agreed set of major deliverables to be produced by the SharePoint project. You also want to know "what's out of scope".
Run the workshop by asking each stakeholder for a list of the deliverables they expect the SharePoint project team to deliver. Take the full list of deliverables generated in the workshop and get them to agree on what's mandatory and what's optional. Then ask them to prioritize the list, so you know what has to be delivered first.

Step 3: Fleshing it out

You now have an agreed list of deliverables. But it's still not enough. You need to define each deliverable in depth. Work with the relevant people in your business to describe how each deliverable will look and feel, how it would operate and how it would be supported etc. Your goal here is to make it so specific that your customer cannot state later in the SharePoint project that "when they said this, they really meant that".

Step 4: Assessing Feasibility

So you now have a detailed list and description of every deliverable to be produced by your SharePoint project, in priority order and separated as mandatory / optional. Great! But is it feasible to achieve within the project end date? Before you confirm the scope, you need to review every deliverable in the list and get a general indication from your SharePoint team as to whether they can all be completed before your SharePoint project end date. If they can't, then which deliverables can you remove from the list to make your end date more achievable?

Step 5: Get the thumbs up

Present the prioritized set of deliverables to your SharePoint project Sponsor and ask them to approve the list as your SharePoint project scope. Ask them to agree to the priorities, the deliverable descriptions and the items out of scope.
By getting formal sign-off, you're in a great position to be able to manage the SharePoint project scope down the track. So when your Sponsor says to you in a few weeks time "Can you please add these deliverables to the list?", you can respond by saying "Yes, but I'll either have to remove some items from the list to do it, or extend the SharePoint project end date. Which is it to be?". You can easily manage your Sponsors expectations with a detailed scope document at your side.

The scope document is the SharePoint project Manager's armor. It protects them from changes and makes them feel invincible!

Thursday, December 9, 2010

TagCloud Webpart in SharePoint 2007

While everyone else right now seems to be blogging about SharePoint 2010, I decided to blog a little bit about the previous product, SharePoint 2007.

Recently, I had to develop a webpart that shows Tags from either a Site collection level or subsite level.

I will give you the code but firstly, here is how it works:

Assumining that you already have a library/list that has a choice field called Category(it can have any name), the webpart will search the site collection/subsite(depending on the scope you choose) for all columns that are named 'Category', and when found, will pull out the selected choices for display. Remember that this is a choice column, meaning that the choices will be repeatitive, and therefore, the more repeative the choices are, the bigger the font size of the Tag name will appear on the webpart.

Secondly, the tags will get random colors on page load, while at the same time will be hyperlinked, and when you click on a tag, it will be passed to the Search and generate search results for you on the search page to library/list items you have permissions on.

Thirdly, on the webpart properties, you get the privilege of changing the choice column name to point to, the scope(site collection or subsite), as well as change the search string to use, and also enable caching etc.

Fouthly, I have a feeling that this is going to be the longest blog post have ever made, nevertheless, the following is the name space code:

**remember to generate your own GUID.

using System;
using System.Data;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.ComponentModel;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace TagCloud.TagCloud
{
[Guid("9eb18673-6617-4c63-b716-8cf8f935318e")]
public class TagCloudClass : System.Web.UI.WebControls.WebParts.WebPart
{
// Fields
private string documentLibraryType = "1";
private bool isActivatedCache = true;
private string listType = "0";
private bool openItemsInNewWindows;
private readonly Random rnd = new Random(DateTime.Now.Millisecond);
private Enumerations.SearchScopes scope = Enumerations.SearchScopes.SiteCollection;
private char separator = ',';
private string tagField = "Category";
private readonly Dictionary Tags = new Dictionary();
private string targetUrl = "/_layouts/OSSSearchResults.aspx?k=";

// Methods
public TagCloudClass()
{
this.rnd = new Random(DateTime.Now.Millisecond);
this.Tags = new Dictionary();
this.documentLibraryType = "1";
this.listType = "0";
this.scope = Enumerations.SearchScopes.SiteCollection;
this.separator = ',';
this.tagField = "Category";
this.targetUrl = "/_layouts/OSSSearchResults.aspx?k=";
this.isActivatedCache = true;
}


private void AddLinks(string key)
{
Tag tag = this.Tags[key];
this.AddSeparator();
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
foreach (TagLink link in tag.Links)
{
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
row.Cells.Add(cell);
HyperLink link2 = new HyperLink();
link2.Text = link.Title;
link2.NavigateUrl = link.ItemUrl;
cell.Controls.Add(link2);
}
this.Controls.Add(child);
}

private void AddSeparator()
{
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
cell.HorizontalAlign = HorizontalAlign.Center;
row.Cells.Add(cell);
Label label = new Label();
label.Text = "----------------";
cell.Controls.Add(label);
this.Controls.Add(child);
}

private void AddTag(DataRow row, string localTag)
{
Tag newTag = new Tag();
newTag.Title = localTag;
SaveTag(newTag, row);
this.Tags.Add(localTag, newTag);
}

private void AddTags(string listType, Enumerations.SearchScopes searchScope)
{
DataTable results = this.GetResults(listType, searchScope);
this.GetTags(results);
}

private void BuildWebPart()
{
try
{
this.AddTags(this.ListType, this.Scope);
this.AddTags(this.DocumentLibraryType, this.Scope);
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
cell.HorizontalAlign = HorizontalAlign.Center;
row.Cells.Add(cell);
this.Controls.Add(child);
foreach (KeyValuePair pair in this.Tags)
{
LinkButton button = new LinkButton();
button.Text = pair.Value.Title;
int count = pair.Value.Links.Count;
button.ToolTip = string.Format("{0} occurrance", count);
button.Font.Size = new FontUnit(GetFontSize(count), UnitType.Point);
button.ForeColor = this.GetRandomColor();
button.CommandArgument = pair.Key;
button.Click += new EventHandler(this.Tag_Click);
cell.Controls.Add(button);
Literal literal = new Literal();
literal.Text = " ";
cell.Controls.Add(literal);
}
}
catch (Exception exception)
{
this.SetErrorMessage(exception);
}
}

protected override void CreateChildControls()
{
base.CreateChildControls();
this.BuildWebPart();
}

private static string GetErrorMessage(Exception ex)
{
StringBuilder builder = new StringBuilder();
try
{
StackTrace trace = new StackTrace(ex, true);
builder.AppendLine(string.Format(" Stack trace for current level: {0}", trace));
StackFrame[] frames = trace.GetFrames();
if (frames != null)
{
foreach (StackFrame frame in frames)
{
builder.AppendLine(string.Format(" File: {0}", frame.GetFileName()));
builder.AppendLine(string.Format(" Method: {0}", frame.GetMethod().Name));
builder.AppendLine(string.Format(" Line Number: {0}", frame.GetFileLineNumber()));
builder.AppendLine(string.Format(" Column Number: {0}", frame.GetFileColumnNumber()));
}
}
}
catch
{
}
return builder.ToString();
}

private static double GetFontSize(int count)
{
double num = 8.0;
switch (count)
{
case 2:
num = 10.0;
break;

case 3:
num = 12.0;
break;

case 4:
num = 14.0;
break;

case 5:
num = 16.0;
break;

case 6:
num = 18.0;
break;

case 7:
num = 20.0;
break;

case 8:
num = 22.0;
break;

case 9:
num = 24.0;
break;
}
if (count > 10)
{
num = 26.0;
}
return num;
}

private static string GetItemUrl(string s)
{
string str = string.Empty;
try
{
string str2 = s.Split(new char[] { '#' })[1];
string str3 = str2.Remove(str2.LastIndexOf('/'));
string str4 = s.Substring(s.LastIndexOf('/') + 1);
string str5 = str4.Remove(str4.LastIndexOf('_'));
str = SPContext.Current.Web.Site.Url + "/" + str3 + "/DispForm.aspx?ID=" + str5;
}
catch (Exception)
{
}
return str;
}

private Color GetRandomColor()
{
Color black = Color.Black;
try
{
int red = this.rnd.Next(0, 0xff);
int green = this.rnd.Next(0, 0xff);
int blue = this.rnd.Next(0, 0xff);
black = Color.FromArgb(red, green, blue);
}
catch
{
}
return black;
}

private DataTable GetResults(string listType, Enumerations.SearchScopes searchScope)
{
string str = "";
string str2 = string.Format("", this.TagField);
string str3 = "";
if (!this.isActivatedCache)
{
SPSiteDataQuery query = new SPSiteDataQuery();
query.Lists = str;
query.ViewFields = str2;
query.Webs = str3;
return SPContext.Current.Web.GetSiteData(query);
}
CrossListQueryInfo queryCacheInfo = new CrossListQueryInfo();
queryCacheInfo.WebUrl = SPContext.Current.Site.ServerRelativeUrl;
queryCacheInfo.Lists = str;
queryCacheInfo.Webs = str3;
queryCacheInfo.Query = string.Format("", this.TagField);
queryCacheInfo.ViewFields = str2;
CrossListQueryCache cache = new CrossListQueryCache(queryCacheInfo);
return cache.GetSiteData(SPContext.Current.Site);
}

private void GetTag(DataRow row, string tag)
{
if (this.Tags.ContainsKey(tag))
{
this.UpdateTag(row, tag);
}
else
{
this.AddTag(row, tag);
}
}

private void GetTags(DataTable results)
{
foreach (DataRow row in results.Rows)
{
string[] strArray = row[3].ToString().Split(new char[] { this.Separator });
foreach (string str in strArray)
{
this.GetTag(row, str.Trim());
}
}
}

private static void SaveTag(Tag newTag, DataRow row)
{
TagLink item = new TagLink();
item.ListID = new Guid(row[0].ToString());
item.WebID = new Guid(row[1].ToString());
item.ItemUrl = GetItemUrl(row[4].ToString());
item.Title = row[5].ToString();
newTag.Links.Add(item);
}

private void SetErrorMessage(Exception ex)
{
this.Controls.Clear();
Label child = new Label();
child.Text = GetErrorMessage(ex);
child.CssClass = "ms-formvalidation";
this.Controls.Add(child);
}

private void Tag_Click(object sender, EventArgs e)
{
LinkButton button = sender as LinkButton;
if (button != null)
{
if (string.IsNullOrEmpty(this.TargetUrl))
{
this.AddLinks(button.CommandArgument);
}
else
{
this.Page.Response.Redirect(this.TargetUrl + button.CommandArgument);
}
}
}

private void UpdateTag(DataRow row, string localTag)
{
Tag newTag = this.Tags[localTag];
SaveTag(newTag, row);
}

// Properties
public string DocumentLibraryType
{
get
{
return this.documentLibraryType;
}
set
{
this.documentLibraryType = value;
}
}

[Personalizable(PersonalizationScope.Shared), FriendlyName("Enable Cache"), Description("Flag for activating the cache"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), WebBrowsable(true)]
public bool IsActivatedCache
{
get
{
return this.isActivatedCache;
}
set
{
this.isActivatedCache = value;
}
}

public string ListType
{
get
{
return this.listType;
}
set
{
this.listType = value;
}
}

[Personalizable(PersonalizationScope.Shared), Description("If checked, allows to open all links in a new window Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), WebBrowsable(true), FriendlyName("Open links in a new window")]
public bool OpenItemsInNewWindows
{
get
{
return this.openItemsInNewWindows;
}
set
{
this.openItemsInNewWindows = value;
}
}

[Category("Parameters"), Personalizable(PersonalizationScope.Shared), FriendlyName("Search Scope"), Description("Set the search scope for Tag: only the current site or the entire site collection"), WebBrowsable(true), PersistenceMode(PersistenceMode.InnerProperty)]
public Enumerations.SearchScopes Scope
{
get
{
return this.scope;
}
set
{
this.scope = value;
}
}

[WebBrowsable(true), Description("Set the value of the separator character for Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), Personalizable(PersonalizationScope.Shared), FriendlyName("Separator character for Tag")]
public char Separator
{
get
{
return this.separator;
}
set
{
this.separator = value;
}
}

[PersistenceMode(PersistenceMode.InnerProperty), Category("Parameters"), Personalizable(PersonalizationScope.Shared), FriendlyName("Tag Name column to search"), WebBrowsable(true), Description("Sets the name tag on the columns to search")]
public string TagField
{
get
{
return this.tagField;
}
set
{
this.tagField = value;
}
}

[WebBrowsable(true), Personalizable(PersonalizationScope.Shared), Description("Set the URL of the page to search for Tag"), FriendlyName("Url of the page to search for Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty)]
public string TargetUrl
{
get
{
return this.targetUrl;
}
set
{
this.targetUrl = value;
}
}

}
internal class TagLink
{
// Fields
private string itemUrl;
private Guid listID;
private string title;
private Guid webID;

// Properties
public string ItemUrl
{
get
{
return this.itemUrl;
}
set
{
this.itemUrl = value;
}
}

public Guid ListID
{
get
{
return this.listID;
}
set
{
this.listID = value;
}
}

public string Title
{
get
{
return this.title;
}
set
{
this.title = value;
}
}

public Guid WebID
{
get
{
return this.webID;
}
set
{
this.webID = value;
}
}
}


internal class Tag
{
// Fields
private List links = new List();
private string title;

// Properties
public List Links
{
get
{
return this.links;
}
set
{
this.links = value;
}
}

public string Title
{
get
{
return this.title;
}
set
{
this.title = value;
}
}
}


public class Enumerations
{
// Nested Types
public enum SearchScopes
{
SiteCollection,
Recursive,
Web
}
}
}



Happy days!!!
References: http://www.codeplex.com/