3

My Favourite SharePoint 2010 Enhancements (for developer) part 1

There are a number of platform and tool enhancements for SharePoint 2010.

I picked out a few favourites which I briefly explain below:
  • LINQ to SharePoint (Language Integrated Query)
  • Data Platform Improvements
  • List Enhancements
  • Business Connectivity Services
  • Silverlight Integration
  • Managed Client Object Model
  • Sandbox Solutions
  • Visual Studio 2010 for SharePoint
  • WSP Changes
  • Developer Dashboard
  • Dialog Framework
  • SharePoint Designer 2010
  • Visio Services
  • InfoPath (changes)
  • Windows PowerShell
LINQ to SharePoint (Language Integrated Query)
LINQ is a feature of the programming languages C# and Microsoft Visual Basic .NET. Compilers are included with Visual Studio.
LINQ adds a SQL-like syntax and vocabulary to each of the languages, which can be used to query data sources. But unlike other languages and query syntaxes which vary from one type of data source to another, LINQ can be used to query, in principle, any data source whatsoever. For this reason, developers may find that it is the only query syntax that they ever need to know.
The LINQ to SharePoint Provider is defined in the Microsoft.SharePoint.Linq namespace. It translates LINQ queries into Collaborative Application Markup Language (CAML) queries. more details here...


Data Platform Improvements
The data platform improvements include: List Relationships, Unique Column Constraints, Data Validation, Column Formula Validation, etc
more details here...

List Enhancements
The list enhancements in SP2010 include: Bulk Operations, New capacity limits(more details here..), XSLT Views (more details here..)

Business Connectivity Services (BCS)
BCS is a set of services and features that provide a way to connect SharePoint solutions to sources of external data and to define external content types that are based on the external data. External content types resemble content types and allow the presentation of and interaction with external data in SharePoint lists (known as external lists), Web Parts, Microsoft Outlook 2010, Microsoft SharePoint Workspace 2010, and Microsoft Word 2010 clients. External systems that Microsoft Business Connectivity Services can connect to include SQL Server databases, SAP applications, Web services (including Windows Communication Foundation Web services), custom applications, and Web sites based on SharePoint. more details here...

Silverlight Integration
In Windows SharePoint Services 3.0, you could host a Microsoft Silverlight application in a Web Part. Microsoft SharePoint Foundation 2010 goes beyond by providing a built-in, extensible, Silverlight Web Part specifically designed to host Silverlight applications. Closely related to the new Web Part is Silverlight Cross-Domain Data Access (Silverlight CDA) that enables secure, cross-domain, integration between Silverlight applications and SharePoint Foundation deployments, and Silverlight CDA can be used by non-Silverlight external applications as well. more details here...

Managed Client Object Model
The SharePoint Foundation 2010 managed client object model lets you write client-side code to work with all the common objects in SharePoint sites. Through the object model, you can add and remove lists, add, update, and delete list items, change documents in document libraries, create sites, manage permissions of items, and add and remove Web Parts from a page.
With the SharePoint Foundation 2010 managed client object model, you can design client applications that access SharePoint content without installing code on the server that runs Microsoft SharePoint Foundation 2010. For example, you can build new categories of applications that include writing applications that are based on the Microsoft .NET Framework, rich interactive Web Parts, Microsoft Silverlight applications, and ECMAScript (JavaScript, JScript) applications that run client-side in a SharePoint Web Part.
more details here...

Sandbox Solutions
You can deploy a Microsoft SharePoint Foundation 2010 solution directly onto your SharePoint Foundation farm, or you can deploy the solution into a sandbox. A sandbox is a restricted execution environment that enables programs to access only certain resources, and that keeps problems that occur in the sandbox from affecting the rest of the server environment.
Solutions that you deploy into a sandbox, cannot use certain computer and network resources, and cannot access content outside the site collection they are deployed in.
more details here... and here.

Visual Studio 2010 for SharePoint
A number of areas for SharePoint developers in Visual Studio 2010 are worth mentioning. First, you get SharePoint project templates in the box, so you can start right away on solution development. Second, tooling has standardized on the Windows SharePoint Package (WSP) packaging standard, so when you import or deploy a solution to SharePoint, Visual Studio treats it as a solution package. Third, some great deployment and packaging features, such as solution retraction and custom deployment configurations, ship with the SharePoint tools in Visual Studio 2010. And last, the new SharePoint Explorer provides a view into native and custom artifacts (for example, lists and workflows) that exist on your SharePoint server.

WSP Changes
SharePoint 2010 improves the WSP format so that it is supported across all tools, allowing you to export your site through the browser, SharePoint Designer, and Visual Studio. This means that you can quickly upgrade or downgrade your solutions between the tools.
SharePoint Online, the Microsoft - hosted version of SharePoint, supports this format so that you can move solutions to the cloud without having to rework the package.

Developer Dashboard
The developer dashboard is a new feature in SharePoint 2010 that is design to provide additional performance and tracing information that can be used to debug and troubleshoot issues with page rendering time. The dashboard is turned off by default, but can be enabled via the object model or stsadm (and PowerShell too, I just haven’t put together the script for it yet). When the dashboard is turned on you will find information about the controls, queries and execution time that occur as part of the page rendering process; this information appears at the bottom of the page.

Dialog Framework
SharePoint 2010 has a new framework for showing dialogs to the end-user. The dialogs allow people to work with some data without losing focus on the page they were working on to get things done. Closing the dialog will often cause AJAX based refreshes to give a sense of stateful-ness.
The dialog is of course extensible through JavaScript code. You can either show a separate page, or use a DOM element on the source page and show that. You can then determine when the dialog closes and what happens when it has closed.
more details here...

SharePoint Designer 2010
There have been a large number of changes to SharePoint Designer.
For a nice overview go to this post

Visio Services
Visio Services in Microsoft SharePoint Server 2010 is a service application that lets users share and view Microsoft Visio Web drawings. The service also enables data-connected Microsoft Visio 2010 Web drawings to be refreshed and updated from various data sources.
Visio Web drawings (*.vdw files) can be rendered by Visio Services and viewed in a Web browser. This lets users view Visio documents without having Visio or the Visio Viewer installed on their local computer. Basic exploration and navigation of these rendered Web drawings are supported within the Visio Web Access Web Part. Page designers can configure the user interface and functionality of the Web Part.
Visio Services can also refresh the data and recalculate the visuals of a Visio Web drawing hosted on a Microsoft SharePoint Server 2010 site. This enables published Web drawings to refresh connections to various data sources and to update affected data graphics and text fields. more details here...

InfoPath 2010 (changes)
InfoPath 2010 comes with a large number of enhancements which includes:
Easy customization of list forms with InfoPath, an InfoPath Form Web Part, Forms with code-behind can be deployed using sandbox solutions, creating a site template will produce a WSP package which includes the InfoPath forms, Forms Services forms now support WCAG 2.0 standard, InfoPath forms can be made available offline using SharePoint Workspace 2010, Forms Services also support FireFox and Safari.
more details here... and here.

PowerShell for SharePoint 2010
Windows PowerShell is a command-line scripting tool that provides an administrator full access to applicable application programming interfaces (APIs), along with the ability to unlock the capability to interact directly with SharePoint 2010 Products to manipulate Web applications, site collections, sites, lists and much more. In addition, the administrator has the ability to script cmdlets (pronounced "command-lets"), which makes for an improved experience from past product versions.  more details here... and here

Other enhancements (not covered in this post):
Access Services
Central Administration (Redesigned)
Digital Asset Management
Enterprise Search
Excel Services
Health Monitoring
Managed Metadata
PerformancePoint Services
Enhanced Records Management
Changes to Social Computing (previous called Collaboration)
Upgrade

Enjoy !!

8

Custom settings for a SharePoint list or library

Someone asked me this week if it is possible to store custom settings (configuration) on a SharePoint (WSS 3.0 and MOSS 2007) list or library.
Example: You have a list or library and you want to create a custom property (metadata)field and provide the user with an GUI to manage a setting value.

I looked into the various options and found it is indeed very simple to accomplish.
 Many thanks to Margriet Bruggeman and Nikander Bruggeman for their contributions.
You can use the Rootfolder object which contains a System.Collections.Hashtable for storing and accessing properties.It is very simple.

To store the value you use:
SPContext.Current.List.RootFolder.Properties[strPropertyKey] = strValue;

SPContext.Current.List.RootFolder.Update ();
 
To retrieve the value you use:
strValue = SPContext.Current.List.RootFolder.Properties[strPropertyKey].ToString();

In order to make it easy for the user to manage such settings, one would add a custom action with Location="Microsoft.SharePoint.ListEdit".
This means that when the user go to a list or library and then select "Settings" a new hyperlink (shortcut) will exist on the settings page from where the custom settings can be managed. (this is not overriding the settings page but rather just adding a shortcut on it)

This tutorial will show how easy it is to develop the described functionality.

Overview:
We will develop the following 2 components:
  1-Feature with Custom Action.
  2-Custom aspx page with code behind to view,insert,edit & delete settings.

Lets get started:

Create a new VS2008 WSPBuilder Project.

















Add a new item to the project. Select WSPBuilder and then 'Blank Feature'















Set the scope of the feature to web.

The Feature.xml file will look like:
<?xml version="1.0" encoding="utf-8"?>

<Feature Id="65a738a0-a095-489e-be19-82c077edea9f"
Title="ListCustomSettings"
Description="Allow Custom Settings on any list"
Version="12.0.0.0"
Hidden="FALSE"
Scope="Web"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>

Now we will use the feature to implement a custom action.
Change the Elements.xml file of the Feature to look like:
<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="Custom.Configuration.ListCustomSettings"
GroupId="GeneralSettings"
Location="Microsoft.SharePoint.ListEdit"
RequireSiteAdministrator="FALSE"
Sequence="100"
Title="Custom Settings">
<UrlAction
Url="_layouts/ListCustomSettings/ListSetting.aspx?List={ListId}" />
</CustomAction>
</Elements>

The feature (as above) will give us a new hyperlink on the List Settings Page (ListEdit). It will look as follow:












The next step is to create a custom page which we can redirect to and on which we can mange the custom settings.

Add a .aspx page to your project with an associated .aspx.cs file.
(there is a little trick to adding this aspx page to the project... please see the footnote at the bottom of this post for step-by-step instructions)

Ensure that the two files are placed inside an appropriate solution folder within the LAYOUTS Folder. Also ensure that the name of the aspx file corresponds to the url used in the custom action definition (above).
<UrlAction Url="_layouts/ListCustomSettings/ListSetting.aspx?List={ListId}" />



















Next we add controls, assembly references etc to our aspx page. I am not going into detail of each line of code as it is standard code.
Ensure your .aspx file look as follow:
(please take special note of the public token key as yours might be different)
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Import Namespace="System.Data" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" Src="~/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" Src="~/_controltemplates/ToolBarButton.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="InputFormSection" src="~/_controltemplates/InputFormSection.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="InputFormControl" src="~/_controltemplates/InputFormControl.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ButtonSection" src="~/_controltemplates/ButtonSection.ascx" %>
<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" AutoEventWireup="true" Inherits="ListConfig.ListConfig, ListCustomSettings,Version=1.0.0.0,Culture=neutral,PublicKeyToken=29d1ff49fe67cd5b" %>
<asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
Custom list config settings page
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
Custom list config settings
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<table width="50%" class="ms-propertysheet" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="ms-error">
<asp:Label ID="lblMessage" runat="server" EnableViewState="False" />
</td>
</tr>
</table>
<table width="50%" class="ms-propertysheet" cellspacing="0" cellpadding="0" border="0">
<tr><td class="ms-descriptionText"><asp:Label ID="LabelMessage" Runat="server" EnableViewState="False" class="ms-descriptionText"/></td></tr>
<tr><td class="ms-error"><asp:Label ID="LabelErrorMessage" Runat="server" EnableViewState="False" /></td></tr>
<tr><td class="ms-descriptionText"><asp:ValidationSummary ID="ValSummary" HeaderText="Errors" DisplayMode="BulletList" ShowSummary="True" runat="server"></asp:ValidationSummary></td> </tr> <tr> <td><img src="/_layouts/images/blank.gif" width="10" height="1" alt="" /></td></tr>
</table>
<table width="50%" border="0" cellspacing="0" cellpadding="0" class="ms-propertysheet">
<!-- Key -->
<wssuc:InputFormSection Title="Key" runat="server">
<Template_Description>
<SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server" text="Specify a key for the entry." EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
</Template_Description>
<Template_InputFormControls>
<wssuc:InputFormControl LabelText="" runat="server">
<Template_control>
<wssawc:InputFormTextBox Title="Key" class="ms-input" ID="txtKey" Columns="35" Runat="server" MaxLength=255 />
</Template_control>
</wssuc:InputFormControl>
</Template_InputFormControls>
</wssuc:InputFormSection>
<!-- Value -->
<wssuc:InputFormSection Title="Value" runat="server">
<Template_Description>
<SharePoint:EncodedLiteral ID="EncodedLiteral2" runat="server" text="Specify the value of the entry" EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
</Template_Description>
<Template_InputFormControls>
<wssuc:InputFormControl LabelText="" runat="server">
<Template_control>
<wssawc:InputFormTextBox Title="Value" class="ms-input" ID="txtValue" Columns="35" Runat="server" MaxLength=255 />
</Template_control>
</wssuc:InputFormControl>
</Template_InputFormControls>
</wssuc:InputFormSection>
<wssuc:ButtonSection runat="server" ShowStandardCancelButton="false">
<template_buttons>
<asp:PlaceHolder ID="PlaceHolderInsertUpdate" runat="server">
<asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" Text="Insert" id="cmdInsertUpdate" OnClick="cmdInsertUpdate_OnClick"/>  
<asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" Text="Cancel" id="cmdInsertUpdateCancel" OnClick="cmdInsertUpdateCancel_OnClick"/>  
</asp:PlaceHolder>
</template_buttons>
</wssuc:ButtonSection>
<br />
<br />
</table>
<SharePoint:SPGridView ID="grdEntries" runat="server" AutoGenerateColumns="false" Width="50%" AllowSorting="True" OnRowDeleting="grdEntries_RowDeleting" OnRowEditing="grdEntries_RowEditing" EnableViewState="false">
<AlternatingRowStyle CssClass="ms-alternating" />
</SharePoint:SPGridView>
<wssuc:ButtonSection runat="server" ShowStandardCancelButton="false">
<template_buttons>
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
<asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" OnClick="cmdOK_OnClick" Text="OK" id="cmdOK" causesvalidation=false />
</asp:PlaceHolder>
</template_buttons>
</wssuc:ButtonSection>
<br />
<br />
<SharePoint:FormDigest ID="FormDigest1" runat="server" />
</asp:Content>

Now we need to code the ListConfig class which is the code-behind of our aspx page.
Open the ListSettings.aspx.cs in code view and add the following code:
using System;

using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Xml;

namespace ListConfig
{
  public partial class ListConfig : LayoutsPageBase
  {
    private DataTable _dtEntries;
    private DataView _dvEntriesView;
    protected SPGridView grdEntries = new SPGridView();
    protected Label lblMessage = new Label();
    protected InputFormTextBox txtKey = new InputFormTextBox();
    protected InputFormTextBox txtValue = new InputFormTextBox();
  }
}

 Next, add a Page_Init event to the ListConfig class. In this event will we add two data columns and two command cokumns to our grid.
protected void Page_Init(object sender, EventArgs e)

{
  BoundField objKeyField = new BoundField();
  objKeyField.ItemStyle.Width = Unit.Percentage(30);
  objKeyField.DataField = "Key";
  objKeyField.HeaderText = "Key";
  grdEntries.Columns.Add(objKeyField);

  BoundField objValueField = new BoundField();
  objValueField.DataField = "Value";
  objValueField.HeaderText = "Value";
  grdEntries.Columns.Add(objValueField);

  CommandField objEditField = new CommandField();
  objEditField.ShowEditButton = true;
  objEditField.HeaderText = "Edit";
  objEditField.ItemStyle.Width = Unit.Pixel(20);
  objEditField.ButtonType = ButtonType.Image;
  objEditField.EditImageUrl = "/_layouts/images/edit.gif";
  grdEntries.Columns.Add(objEditField);

  CommandField objDeleteField = new CommandField();
  objDeleteField.ShowDeleteButton = true;
  objDeleteField.HeaderText = "Delete";
  objDeleteField.ItemStyle.Width = Unit.Pixel(20);
  objDeleteField.ButtonType = ButtonType.Image;
  objDeleteField.DeleteImageUrl = "/_layouts/images/delete.gif";
  grdEntries.Columns.Add(objDeleteField);
}


Next, add a Page_Load event to the ListConfig class. In this event we set allowunsafeupdates=true and we bind the grid to data.
protected void Page_Load(object sender, EventArgs e)

{
  SPContext.Current.Web.AllowUnsafeUpdates = true;
  BindGrid();
} 

Next, add a LoadData function to help load the data into the datatable. You will notice the important thing here is that we iterate through the RootFolder.Properties.Keys to get all custom settings for the current list, and then we load the data in to the datatable.
private void LoadData(string strSortOrder)

{
_dtEntries = new DataTable();
DataColumn objKeyColumn = new DataColumn();
objKeyColumn.DataType = Type.GetType("System.String");
objKeyColumn.ColumnName = "Key";
objKeyColumn.ReadOnly = true;
_dtEntries.Columns.Add(objKeyColumn);

DataColumn objValueColumn = new DataColumn();
objValueColumn.DataType = Type.GetType("System.String");
objValueColumn.ColumnName = "Value";
objValueColumn.ReadOnly = true;
_dtEntries.Columns.Add(objValueColumn);

foreach (string strKey in SPContext.Current.List.RootFolder.Properties.Keys)
{
if (strKey.StartsWith("vti_")) continue;
if (strKey.StartsWith("_reporting")) continue;
if (SPContext.Current.List.RootFolder.Properties[strKey] == null) continue;
if (SPContext.Current.List.RootFolder.Properties[strKey].ToString() == String.Empty) continue;

DataRow objRow = _dtEntries.NewRow();
try
{
objRow["Key"] = strKey;
}
catch
{
objRow["Key"] = "Error";
}
try
{
objRow["Value"] = SPContext.Current.List.RootFolder.Properties[strKey];
}
catch
{
objRow["Value"] = "Error";
}
_dtEntries.Rows.Add(objRow);
}
_dvEntriesView = _dtEntries.DefaultView;
_dvEntriesView.Sort = "[Key] asc";
}

Next, add a helper function to populate the grid:
private void BindGrid()

{
try
{
LoadData(String.Empty);
grdEntries.DataSource = _dvEntriesView;
grdEntries.DataBind();
}
catch (Exception err)
{
lblMessage.Text = lblMessage.Text + "Failed to bind data to page. Please try to reload the page.";
}
}

Add Event handlers for the grid behaviour:
public void grdEntries_RowDeleting(object sender, GridViewDeleteEventArgs e)

{
try
{
string strKey = grdEntries.Rows[e.RowIndex].Cells[0].Text;
strKey = SPHttpUtility.HtmlDecode(strKey);
if (SPContext.Current.List.RootFolder.Properties.ContainsKey(strKey))
{
SPContext.Current.List.RootFolder.Properties[strKey] = null;
SPContext.Current.List.RootFolder.Update();
}
BindGrid();
}
catch (Exception err)
{
lblMessage.Text = lblMessage.Text + err.Message + "\n";
}
}

public void grdEntries_RowEditing(object sender, GridViewEditEventArgs e)
{
string strKey = grdEntries.Rows[e.NewEditIndex].Cells[0].Text;
txtKey.Text = strKey;
txtKey.Enabled = false;
txtValue.Text = SPContext.Current.List.RootFolder.Properties[strKey].ToString();
}

public void grdEntries_Sorting(object sender, GridViewEditEventArgs e)
{
grdEntries.DataSource = _dvEntriesView;
grdEntries.DataBind();
}

Add a helper function to build a redirect url (which will be used when the form close):
private string GetRedirectUrl()

{
return SPContext.Current.Web.Url + String.Format("/_layouts/listedit.aspx?List={0}", Request.QueryString["List"]);
}

Add the Button Click Events which corresponds to the definition in the aspx file:
public void cmdOK_OnClick(object sender, EventArgs e)

{
SPUtility.Redirect(GetRedirectUrl(), SPRedirectFlags.UseSource, HttpContext.Current);
}

public void cmdInsertUpdate_OnClick(object sender, EventArgs e)
{
try
{
string strKey = txtKey.Text;
if (strKey.Length == 0)
{
throw new Exception("You must provide a key.");
}
if (strKey.Contains("&"))
{
throw new Exception("& is not allowed. You must provide an alternative name.");
}
string strValue = txtValue.Text;
if (strValue.Length == 0)
{
throw new Exception("You must provide a value.");
}
if (SPContext.Current.List.RootFolder.Properties.ContainsKey(strKey))
{
SPContext.Current.List.RootFolder.Properties[strKey] = strValue;
}
else
{
SPContext.Current.List.RootFolder.Properties.Add(strKey, strValue);
}
SPContext.Current.List.RootFolder.Update();
strKey = "";
strValue = "";
txtKey.Text = "";
txtKey.Enabled = true;
txtValue.Text = "";
BindGrid();
}
catch (Exception err)
{
lblMessage.Text = err.Message;
}
}

public void cmdInsertUpdateCancel_OnClick(object sender, EventArgs e)
{
txtKey.Text = "";
txtKey.Enabled = true;
txtValue.Text = "";
}

Override the OnUload event of the page to set the AllowUnsafeUpdates=false:
protected override void OnUnload(EventArgs e)

{
SPContext.Current.Web.AllowUnsafeUpdates = false;
}

WOW, it looks like a lot of code, but in fact, its not much!
Next, build your project and if all is successfull you are ready to test the outcome.

Go to your project properties and set the 'start browser with' setting to the target SP site url on which you want to test.













Save your project. Right click on your project, select WSPBuilder and then select "Build WSP" - keep an eye on the output pane to ensure that there are no problems. Once successful, right click on the project, select WSPBuilder and then select "Deploy". 
Once done, go to the target SP site and refresh the site features list.
You will notice the following new site feature is available:






Activate the feature.
Go to any list or library and open the settings page.














You will notice the new Custom Action URL which we added:













When you click on the 'custom settings' custom action url you will be redirected to the new custom page:










On this page you can manage custom settings for the list.












There you go ! a very nice tool which can be used to store custom settings on any list or library.

Enjoy !!!

Note: Trick to add a aspx page to the project:
If you want to add a aspx page to the project you click on project and select "Add New Item..." but you will notice that the Web Form / .aspx item is not available to be selected.
When you want to add a aspx page with an associated aspx.cs file to the project there is a little trick that you need to do.
Open another instance of Visual Studio.
Select to create a new project and choose C# --> ASP.Net Web Application
















Provide a projace name and click on "OK".
Once the project has been created you will see it contains a web form (aspx).
Open the Solution Explorer view --> right click and select "Open Folder in Windows Explorer".






















From Windows Explorer copy the aspx file and aspx.cs file into your SharePoint project folder (where the solution of this tutorial project is located) and then in your project add an existing item and select the two files which you copied.

3

Silverlight in SharePoint - Option 2 - Custom Web Part Feature

In two previous tutorials I showed how to create a simple Silverlight application, and how to use a Silverlight application inside SharePoint (WSS 3.0 or MOSS 2007) using a Content Editor Web Part.

There are a lot of conflicting and even unclear instructions on the web on how to achieve this.
Thank you Karine Bosch for the excellent post you made available. It is very well structured and helped me immensely in putting together this post for my team. The original blog post which a lot of my information come from can be found at http://karinebosch.wordpress.com/2009/07/17/integrating-silverlight-3-in-sharepoint-2007/

In this tutorial I will show how to develop a proper custom SharePoint web part feature which encapsulates the Silverlight application.


Please note that the example I give is very basic. It will be easy to make the web part more generic - you can add web part properties in which which the user can specify the height, width, and .xap file location. If you add the custom properties you will have a reusable Silverlight container web part.

Important:
This tutorial is for Silverligh 3 - there has been changes from Silverlight version 2 which you need to consider. (SL3 does not contain the System.Web.Silverlight.dll)

Prerequisites:
       Silverlight 3 Tools for Visual Studio (download here)
       SharePoint (WSS 3.0 or MOSS 2007)
       Visual Studio 2008
       A working Silverlight application (see this tutorial to create one)
       WSP Builder (to develop the SharePoint Web Part)

Lets Create our SharePoint Web Part:
Create a new Visual Studio 2008 project.
Select "WSPBuilder" from project type and  "WSP Builder Project" from Templates.














Right-click on the project and add a new item. Select WSPBuilder from Categories and "Web Part Feature" from Templates.













Provide a description for the web part and set the Scope to "Site"












In the Solution Explorer, create a LAYOUTS folder under TEMPLATES and then create 2 new folders under the LAYOUTS folder. Name the 2 new folders "SL3" and "XAPS".
Inside the XAPS folder add an existing working Silverlight 3 application.
(see this tutorial to create one)




















Now we have a structure to build our web part code and we have a Silverlight application which we can display in our web part.
Next we will add two Silverlight helper files. (which enables Web sites to create advanced Silverlight installation and instantiation experiences)

In Windows Explorer locate the Silverlight.js file from the C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Tools folder.
Copy this file to the SL3 folder of your project.
(For more information on Silverligth.js please see this site.)

In Visual Studio Solution Explorer switch-on the "view all files" option, refresh your solution and then right click on Silverlight.js and select "Include in project". Alternatively use the "add to project" functionality.

Right Click on the SL3 folder and select "Add" --> "New Item"
Select Visual C# Items and Select JScript File.
Name the File SharePointSilverLightHelper.js













Once the file is added to your solution, open the file and add the following script to create a Silverlight application based on the silverlight.CreateObjectEx method:
function onSilverlightError(sender, args)
{
var appSource = "";
if (sender != null && sender != 0)
{
 appSource = sender.getHost().Source;
}
var errorType = args.ErrorType;
var iErrorCode = args.ErrorCode;
var errMsg = "Unhandled Error in Silverlight Application " + appSource
+ "\n" ;
errMsg += "Code: "+ iErrorCode + " \n";
errMsg += "Category: " + errorType + " \n";
errMsg += "Message: " + args.ErrorMessage + " \n";
if (errorType == "ParserError")
{
 errMsg += "File: " + args.xamlFile + " \n";
 errMsg += "Line: " + args.lineNumber + " \n";
 errMsg += "Position: " + args.charPosition + " \n";
}
else if (errorType == "RuntimeError")
{
 if (args.lineNumber != 0)
 {
  errMsg += "Line: " + args.lineNumber + " \n";
  errMsg += "Position: " + args.charPosition + " \n";
 }
 errMsg += "MethodName: " + args.methodName + " \n";
}
 throw new Error(errMsg);
}


function createSL(divid, swidth, sheight, source, initparameters)
{
  var pluginid = divid + "Plugin";
  var divElement = document.getElementById(divid);
  var altHTML = divElement.innerHTML;
  if (swidth == null)
   {swidth='100%';}
  if (sheight == null)
   {sheight='750px';
}
  Silverlight.createObjectEx(
 {  source: source,
    parentElement: divElement,
    id: pluginid,
    properties:
    {
     width:swidth, 
     height:sheight,
     minRuntimeVersion:'2.0.31005.0'
  },
   events:
   {
    OnError: onSilverlightError 
   },
   initParams: initparameters
   }
  );
}
 
The solution file structure should look like this:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Save the Visual Studio solution.
 
Next, we will add the web part code to render the Silverlight application inside SharePoint.

Open your web part class (in this example SharePointSilverLightWebPart1.cs) in code view and remove all the unneccesary code so that the class is nice and clean:
using System;
using System.Collections.Generic;

using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Text;

namespace SharePointSilverLightWebPart1
{
   [Guid("848d4aec-5dd2-4b7d-a512-995191a627e8")]
   public class SharePointSilverlightWebPart1 :  
          Microsoft.SharePoint.WebPartPages.WebPart
   {
   }
}

Add the following declaration inside the class:
private LiteralControl silverlightHost;

Add code to the OnPreRender event to register the javascript files.
protected override void OnPreRender(EventArgs e)
{
  base.OnPreRender(e);
  ClientScriptManager cs = Page.ClientScript
  if (!cs.IsClientScriptIncludeRegistered("sl_javascript"))
     cs.RegisterClientScriptInclude(this.GetType(),
     "sl_javascript", "/_LAYOUTS/SL3/Silverlight.js");
  if (!cs.IsClientScriptIncludeRegistered("spsl_javascript"))
    cs.RegisterClientScriptInclude(this.GetType(), 
    "spsl_javascript", /_LAYOUTS/SL3/SharePointSilverLightHelper.js");
}

Call the above javascript from within the CreateChildControls method:
protected override void CreateChildControls()
{
  string xaplocation = null;
  xaplocation = "_LAYOUTS/Xaps/SilverlightApplication1.xap";
  Unit height = new Unit(500);
  string slstring = string.Format("<script 
  type=\"text/javascript\">createSL('silverlightHost', '{0}', 
  '{1}', '{2}', '{3}');</script>", height, height, xaplocation, 
  "");
  silverlightHost = new LiteralControl(string.Format("<div  
  id=\"silverlightHost\" style=\"width:100%; height:100%\"></div>
  {0}", slstring));
  this.Controls.Add(silverlightHost);
}

To test the solution, add a SharePoint site URL to the Debug settings of the project.


















Save the project. Build the project. Use WSP Builder to "Build WSP" and then to "Deploy"
Navigate to the same SharePoint site in I.E. and go to Site Settings -->Site Collection Features. Activate your new feature.














Edit a web part page on your site and add the following web part:










See the new web part containing the Silverlight solution.

Enjoy !!

0

Silverlight in SharePoint Option 1 - CEWP

This simple tutorial will illustrate how to embed a Silverlight application (.xap file) in SharePoint (WSS 3 or MOSS 2007) using a Content Editor web part.

Many thanks to my friend Hassan-Mia Salie for his contributions.

Prerequisites:
   Silverlight 3.0 Client
   SharePoint (WSS3 or MOSS)
   A Working Silverlight application (.xap file)
   (to see how to create a simple silverlight app check out this tutorial)

Lets Go:
Locate the web application folder of your SharePoint application.
Should be: C:\inetpub\wwwroot\wss\VirtualDirectories\1000\ ,where "1000" is the number of your SharePoint Web App IIS port.

Create a new “ClientBin” folder in the web application folder.










Open you SharePoint Web which exist within the same web application.

Edit a Page and add a CEWP.
Select to modify the shared web part and open the “Source Editor...”
Paste the following code.
(please note the name of your silverlight file - the file I used was called MySilverLightApp.xap.)

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/MySilverLightApp.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>

Change the width and height from % to values.

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="400" height="400">
<param name="source" value="ClientBin/MySilverLightApp.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
</object>

Save the CEWP and refresh the page.... you will see you Silverlight app in SharePoint.
















Enjoy !!