Posts
52
Comments
22
Trackbacks
0
Thursday, April 26, 2012
Develop SharePoint Solutions without installing SharePoint on Visual Studio
If you want to stay away from installing SharePoint on your client OS (Windows 7) but still develop cutting edge solutions, webparts etc for a SharePoint server running on a different VM. 

You can just open up Visual Studio without firing up a VM and code!

Here's a trick to that: Put the SharePoint assemblies on your local machine and make my own SharePoint Root (aka “14 folder”) on my Windows 7 machine. It’s easy enough, but maybe you want to check the differences between different releases (RTM, SP1, CU’s, etc).

You can use PowerShell to extract all the DLL’s from the SharePoint Root folder and put them in a place I keep documentation, snippets, etc on my machine. For example, I’ll have a folder that looks like this:

c:\Dev\Ref\SharePoint\14 (4762.1000 – RTM)\

Try to include only the DLL’s because the SharePoint Root is huge. 

For SharePoint 2010 RTM, just the DLLs are about 60MB. Go to the place where the SharePoint Root is when it’s installed and add a symbolic link that points to it like this (from an administrator command prompt):

c:\[Path to Web Server Extensions]]>mklink /d 14 “c:\Dev\Ref\SharePoint\14 (4762.1000 – RTM)”

Now navigate to the 14 folder and go to the same place where you find it on an installed machine. If you want to switch to something like SP1, then you copy those same assemblies and recreate the 14 link to point to the new folder.

Enjoy the ease of developing without any admin :)

Posted On Thursday, April 26, 2012 11:07 AM | Comments (0)
Web Part to execute CAML Query - Using 'Managed Metadata' entered user

I came across a requirement where I needed a way to be able to retrieve pages that have been tagged with a particular Managed Metadata (MMD) value. 

Let's say there's a MMD field called Category. And the users should be able to use the Taxonomy "picker" control to select which category value they want to filter their results by.

Let's create a WebPart to do this. Use the Web Part Tool Pane EditorPart, add it to your Web Part for filtering. The EditorPart doesn't do the actual persisting of the data, so I need to create public properties on the parent Web Part that store the selected value. My web part, "MyWebPart" has the following three public properties:

int[] CategoryWssIds
string FilterTerm
Guid CategoryTermId

The picker control should bound to the same node that my Category site column is already bound to, in the MMD tree.

Here's the code for the EditorPart class:

class Editor : EditorPart
{
private TaxonomyWebTaggingControl termPicker;

/// <summary>
/// Adds the picker control and binds it to the same term set that the
/// Category site column is bound to.
/// </summary>
protected override void CreateChildControls()
{
try
{
TaxonomyField category = SPContext.Current.Site.RootWeb.Fields["Category"] as TaxonomyField;

if (categories != null)
{
TaxonomyWebTaggingControl termPicker = new TaxonomyWebTaggingControl();
termPicker.SspId.Add(categories .SspId);
termPicker.TermSetId.Add(category.TermSetId);
termPicker.AllowFillIn = false;
termPicker.IsMulti = false;
termPicker.Width = 170;

this.Controls.Add(termPicker);
}
}
catch (Exception e)
{
//Display error message
}
}

/// <summary>
/// Takes the term that was selected by the user in the picker control, and
/// saves its properties to the parent web part's properties.
/// </summary>
/// <returns>A flag indicating whether the changes could be saved or not.</returns>
public override bool ApplyChanges()
{
try
{
termPicker = (TaxonomyWebTaggingControl)this.Controls[0];

//Evaluate if the user has picked a term
string selectedTaxValue = termPicker.Text;
int separatorIndex = selectedTaxValue.IndexOf("|");
if (selectedTaxValue != string.Empty && separatorIndex != -1)
{
//If the user has selected a term, save that term and its lookup list id (or ids, if there are child terms)
//to the parent web part. (The lookup ids are the ids of the term in the TaxonomyHiddenList in the current
//site collection.)
TaxonomyField category = SPContext.Current.Site.RootWeb.Fields["Category"] as TaxonomyField;
Guid termSetId = category.TermSetId;
TaxonomySession session = new TaxonomySession(SPContext.Current.Site);
Guid termId = new Guid(selectedTaxValue.Substring(separatorIndex + 1));
string filterTerm = selectedTaxValue.Substring(0, separatorIndex);
int[] wssIds = TaxonomyField.GetWssIdsOfTerm(SPContext.Current.Site, session.TermStores[0].Id, termSetId, termId, true, 100);
if (wssIds.Length > 0)
{
MyWebPart myWebPart = this.WebPartToEdit as MyWebPart;
myWebPart.CateogryWssIds = wssIds;
myWebPart.FilterTerm = filterTerm;
myWebPart.CategoryTermId = termId;
myWebPart.SaveChanges();
}
else
{
return false;
}
}
}
catch (Exception e)
{
return false;
}

return true;
}

/// <summary>
///Retrieves the properties stored in the web part and sets the value of the
/// metadata picker control based on them.
/// </summary>
public override void SyncChanges()
{
EnsureChildControls();

termPicker = (TaxonomyWebTaggingControl)this.Controls[0];
MyWebPart myWebPart = this.WebPartToEdit as MyWebPart;

if (myWebPart.CateogryWssIds != null &&
myWebPart.CateogryWssIds.Length != 0 &&
termPicker.Text == string.Empty)
{
termPicker.Text = String.Format("{0}|{1}", myWebPart.FilterTerm,
myWebPart.CategoryTermId.ToString());
}
}
}

Now that I have an EditorPart, I need to add it to MyWebPart. I can do it like this:

public override EditorPartCollection CreateEditorParts()
{
Editor editor = new Editor();
editor.ID = this.ID + "_Editor";
editor.Title = "Filter Term";
List editors = new List();
editors.Add(editor);
return new EditorPartCollection(editors);
}

Add the following method to make sure the changes made by the Editor part get persisted to the web part:

public void SaveChanges()
{
this.SetPersonalizationDirty();
}

When it's time to build my CAML query string, I do it like this:

StringBuilder values = new StringBuilder();
for (int i = 0; i < categoryWssIds.Length; i++)
{
values.Append("<Value type='Integer'>");
values.Append(categoryWssIds[i].ToString());
values.Append("</Value>");
}

string query = String.Format(@"<Where>
<In>
<FieldRef name="Category" LookupId="TRUE"/><Values>{0}</Values>
</In>
</Where>", values.ToString());

One thing to keep in mind is that this is querying the hidden list in the current site collection that stores all the MMD values that have been used. So, if you haven't used a particular term yet anywhere in your site, the GetWssIdsOfTerm method won't give you anything back.
Posted On Thursday, April 26, 2012 10:56 AM | Comments (0)