Wednesday, December 09, 2009

Sharepoint Shared Services Roll-up for Windows Server 2008 R2

I decided to play around with Managed MetaData Service today. On trying to open the properties page through Central Admin, I came across this error:

The Managed Metadata Service or Connection is currently not available. The Application Pool or Managed Metadata Web Service may not have been started. Please Contact your Administrator.

To resolove, I had to apply the hot fix KB976462 and restart my machine.
http://support.microsoft.com/kb/976462

My first Hot Fix for SP2010 :-) . Its actually a hotfix for the .NET Framework 3.5 Service Pack 1 and a prerequisite for SharePoint 2010 beta.

I am now able to view the Term Store Managemet Tool, and this should allow me to move ahead with my exploration.

Sunday, November 29, 2009

Import a SharePoint Designer Reusable Workflow

While trying to import the reusable workflow into Visual Studio, I got an error with message:


Parameter Name: relativePath

As a work around, I saved the entire site as template, saved the WSP file to my machine, and then imported only the required Workflow into Visual Studio. This workaround is described here:

http://msdn.microsoft.com/en-us/library/ee231580(VS.100).aspx

Any other alternatives to overcome the Parameter Name: relativePath error?

Chart Web Part

I used the new SharePoint 2010 "Chart Web Part" today, and I am already in love with it. As its name suggests, it is used to generate charts based on a data source (another web part, SharePoint List, BDC, Excel Services). It provides an easy to configure wizard that even a 10 year old kid can use. I will let the screen shots do most of the talking in this blog to give you a quick overview of its features and functionality.
To begin, you need to active go to Site Actions, Site Settings, Site collection features, and activate "SharePoint Server Enterprise Site Collection features".




On your page where you want to display the chart, click on Edit Page, Insert, Web Part. The web part is found under the Miscellaneous section.


It will add the Web Part to the page.


To begin configuration, click on "Data and Appearance".


Select "Connect Chart To Data".



Select "Connect to List" and click Next


Select your site and your List and click Next


If your list had, say Sales by Year data, you could use the "Filter Data" option to filter data to a particular year.


For this blog, I will not filter and instead use all the data present in the list.

Select your X and Y fields and click Finish.

To change the chart type, click on "Data and Appearance" and then "Customize Your Chart".



Click on "Standard Chart Types" tab.





There is a range of options. I will select "Pie" under Chart Type Categories.



There are different types of pie charts available. Select the one you wish to use and click on Next.

Select a suitable appearance matching your site theme, and the required size.




I plan to show a legend, so I decided to set the Width to be double of the Height.  I selected the following options:

Theme: Light Steel Blue
Chart Width: 800 px
Chart Height: 400 px
Chart Image Format: Jpeg

Note that the chart image type will decide the image type rendered on the page.

Check "Chart Title" and "Show Legend".



Set Chart Title as "Sales By Year" and set the position to Bottom Center.



Click "Finish" to exit the wizard and view the chart on the page.



Click on "Edit Web Part" to review and change the chart and other web part settings.



For basic charts and graphs scenarios, it is likely to replace Excel Services and SSRS. What do you think?

So simple, yet so powerful.

Friday, November 06, 2009

SharePoint Client Object Model

SharePoint Client Object Model is the new programming interface to access SharePoint data from a remote client machine.

Client OM unifies the programing model and can be called from JavaScript, .Net Code (Win Forms, Console App) or Silverlight Application.

Let’s program using the Client OM for a Win Forms application.

Add a reference to the following assemblies:

Microsoft.SharePoint.Client.Silverlight.dll
Microsoft.SharePoint.Client.Silverlight.Runtime.dll

Add a reference to the following namespace:
using Microsoft.SharePoint.Client;

Add 2 list boxes and a button onto your form.

To populate the List and the List Items, add the following code to the button click event:


string siteURL = "http://moss.contoso.com/sites/MySpace";

using (ClientContext ctx = new ClientContext(siteURL))
{
     //Get List Names
     Web site = ctx.Web;
     ctx.Load(site);
     ctx.Load(site.Lists);

     //Executes the current set of data retrieval queries and method invocations
     ctx.ExecuteQuery();

     foreach (List list in site.Lists)
     {
          listBox1.Items.Add(list.Title);
     }
}

//Get List Items from "Announcements" List
using (ClientContext ctx = new ClientContext(siteURL))
{
     string listTitle = "Announcements"; //listBox1.SelectedItem.ToString()
     Web site = ctx.Web;

     //Load List
     ctx.Load(site,
                s => s.Lists.Where(l => l.Title == listTitle));
     ctx.ExecuteQuery();
     List list = site.Lists[0];

     //Get items for the list

     CamlQuery query2 = new CamlQuery();
     ListItemCollection lc = list.GetItems(query2);
     ctx.Load(lc);
     ctx.ExecuteQuery();

     //Display Announcements Title
     foreach (ListItem item in lc)
     {
          listBox2.Items.Add(item["Title"].ToString());
     }
}

Note that you need to first Load(), and only then call ExecuteQuery().
Accessing the list item without calling Load and ExecuteQuery throws CollectionNotInitializedException.

Thursday, November 05, 2009

SharePoint 2010 Events

SharePoint 2010 introduces a number of different event receivers that developers can take advantage of.

There are 5 types of events which can be captured:
1. List Events
2. List Item Events
3. List Email Events
4. Web Events
5. List Workflow Events

After events can now be synchronous (Before events are synchronous and After events are asynchronous by default).

Visual Studio 2010 provides Event Receiver template. It will help developers quickly jumpstart the process.






The list of events is given below.

SPListEventReceiver: Provides methods to trap events that occur for lists.

ListAdded : Event that occurs after a list is added to a Web site.
ListAdding : This event is registered at the Web site or site collection where the list is created.
ListDeleting : Event that occurs before a list is deleted.
ListDeleted : Event that occurs after a list is added to a Web site.
FieldAdded : Occurs after a field link is added.
FieldAdding : Occurs when a field link is being added to a content type.
FieldDeleted : Occurs after a field has been removed from the list.
FieldDeleting : Occurs when a field is in the process of being removed from the list.
FieldUpdated : Occurs after a field link has been updated
FieldUpdating : Occurs when a field link is being updated


SPItemEventReceiver: Provides methods for trapping events that occur to items.

ItemAdded : Asynchronous After event that occurs after a new item has been added to its containing object.
ItemAdding : Synchronous Before event that occurs when a new item is added to its containing object.
ItemAttachmentAdded : Asynchronous After event that occurs after a user adds an attachment to an item.
ItemAttachmentAdding : Synchronous Before event that occurs when a user adds an attachment to an item.

ItemAttachmentDeleted : Asynchronous After event that occurs when after a user removes an attachment from an item.

ItemAttachmentDeleting : Synchronous Before event that occurs when a user removes an attachment from an item.

ItemCheckedIn : Asynchronous After event that occurs after an item is checked in.
ItemCheckedOut : Asynchronous After event that occurs after an item is checked out.
ItemCheckingIn : Synchronous Before event that occurs as a file is being checked in.
ItemCheckingOut : Synchronous Before event that occurs after an item is checked out.
ItemDeleted : Asynchronous After event that occurs after an existing item is completely deleted.
ItemDeleting : Synchronous Before event that occurs before an existing item is completely deleted.

ItemFileConverted

ItemFileMoved : Occurs after a file is moved.
ItemFileMoving : Occurs when a file is being moved.
ItemUncheckedOut : Synchronous Before event that occurs when an item is being unchecked out.
ItemUncheckingOut : Synchronous Before event that occurs when an item is being unchecked out.

ItemUpdated : Asynchronous After event that occurs after an existing item is changed, for example, when the user changes data in one or more fields.

ItemUpdating : Synchronous Before event that occurs when an existing item is changed, for example, when the user changes data in one or more fields.


SPWebEventReceiver: Provides methods for trapping events that occur to Web sites.

SiteDeleted : Occurs after a site collection has been deleted.
SiteDeleting : Occurs when a site collection is being deleted.
WebDeleted : Asynchronous After event that occurs after an existing Web site is completely deleted.
WebDeleting : Synchronous Before event that occurs before an existing Web site is completely deleted.
WebMoved : Asynchronous After event that occurs after an existing Web site has been moved.

WebMoving : Synchronous Before event that occurs before an existing Web site has been renamed or moved to a different parent object.

WebAdding : Synchronous Before event that occurs before a new Web site is created.

WebProvisioned : Synchronous After event that fires after the Web is fully provisioned and the provisioning process has stopped.


SPEmailEventReceiver: Provides a method for trapping the event when a list receives an e-mail message.

EmailReceived : Occurs after an e-mail message has arrived.


SPWorkflowEventReceiver:

WorkflowCompleted : A workflow was completed
WorkflowPostponed : A workflow was postponed
WorkflowStarted : A workflow was started
WorkflowStarting : A workflow is starting
Note: This documentation is preliminary and is subject to change.

Tuesday, November 03, 2009

Visual Web Part is the new Smart Part

Visual Studio 2010 comes with a template for VisualWebPart.

It creates a web part (.cs), User Control (.ASCX) and other associated files.

The Web Part maintains a reference to the User Control and loads the same in the CreateChildControls method.

private const string _ascxPath = @"~/_CONTROLTEMPLATES/ContosoWebParts/FirstWebPart/MyUserControl.ascx";

protected override void CreateChildControls()
{
  Control control = this.Page.LoadControl(_ascxPath);
  Controls.Add(control);
  base.CreateChildControls();
}


The actual functionality can be developed in the Web User Control (MyUserControl.ascx) which can leverage the Visual Studio Designer


The approach is similar to Return of Smart Part for MOSS 2007, which we used to wrap ASCX file within an web part.

Sunday, November 01, 2009

STSADM SPMETAL

STSADM.EXE is now loacted at:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN

From 12\BIN to 14\BIN, thats the only change, as there is no Version 13 (considered unlucky by many).

The new SPMETAL.EXE, which is used to genrate Entity Classes for LINQ to SharePoint, also resides inside 14\BIN.

Developer Dashboard for SharePoint Performance Monitoring

One of the new useful features SharePoint 2010 introduces is the Development Dashboard. It provides detailed diagnostic information for each page load at the bottom of the page. It is turned Off by default. The setting can be modified using SharePoint Object Model, STSADM.exe or PowerShell.


Below is the object model code snippet to change the settings using object model:

SPPerformanceMonitor SPPerfMon = SPFarm.Local.PerformanceMonitor;
SPPerfMon.DeveloperDashboardLevel = SPPerformanceMonitoringLevel.On;
//SPPerfMon.DeveloperDashboardLevel = SPPerformanceMonitoringLevel.OnDemand;
//SPPerfMon.DeveloperDashboardLevel = SPPerformanceMonitoringLevel.Off;
SPPerfMon.Update();

Setting it to On shows the page diagnostics, load time and other information at the bottom of the page.






Setting it to OnDemand makes the icon appear at the upper right hand side of the page. Clicking on the icon makes the Developer Dashboard appear and disappear on the page.

Using STSADM.exe, the scripts are:

stsadm -o setproperty -pn developer-dashboard -pv on
stsadm -o setproperty -pn developer-dashboard -pv off
stsadm -o setproperty -pn developer-dashboard -pv OnDemand


Everything that can be done in STSADM should be possible in PowerShell too. You can explore it on your own.
I am wondering if there is an option yet on the UI to manage the Developer Dashboard setting. Anyone knows?
The setting is only at the SPFarm level. It would be better if we we have an option to turn this on at the Site Collection or Site Level.


Updates:
The above code does not work on the updated SP2010 vesion. Try this instead:

SPWebService cs = SPWebService.ContentService;

cs.DeveloperDashboardSettings.DisplayLevel = SPDeveloperDashboardLevel.OnDemand; //or On or Off
cs.DeveloperDashboardSettings.Update();

You need to refer to the Microsoft.SharePoint.Administration namespace.

Saturday, October 24, 2009

Refinement Panel

The name “Faceted Search” was not intuitive to a lot of people. Every first timer would ask me ‘What does it do?’


Well, seems like there were others who asked the same question.

The web part has now been renamed to “Refinement Panel”. Sounds less geeky, but easier for the business users to understand its functionality.

Thursday, October 22, 2009

Microsoft SharePoint Designer 2010 Backward Compatibility

Microsoft SharePoint Designer 2010 cannot be used to open MOSS 2007 sites. On trying to do so, it gives this message “Microsoft SharePoint Designer cannot be used to edit web sites on servers prior to Microsoft SharePoint Server 2010. To edit these sites, you need to use SharePoint Designer 2007”





And it goes without saying that SPD 2007 cannot be used to open SharePoint 2010 sites.

Both SPD 2007 and SPD 2010 can be installed on the same machine, so not a real issue.

Tuesday, October 20, 2009

Good bye stsadme.exe, Time to learn Windows PowerShell

Although a version of Windows Powershell was available on the Win 2008 machine that I use, I never really paid any serious attention to this tool. But since Windows Powershell is expected to replace good old stsadm.exe, it’s time for me to ramp up.


Stsadme.exe will continue to be supported for back word compatibility. However, if stsadm.exe can do something, Windows Powershell will also be able to do the same. And with higher efficiency most of the times.

Stsadm.exe, good old friend, we will miss you. Rest In Peace

SharePoint 2010 Launched

SharePoint 2010 Beta was launched to the world today at the SharePoint 2010 conference in Las Vegas. I have never been so earnestly awaiting the launch of any other product.
I plan to be a devout student and learn and share my experiences through this blog.
Amongst the range of new features that SharePoint 2010 introduces, it now provides support for multiple browsers.


Level 1 Internet browser options running on the Windows® operating system:
  • Windows Internet Explorer® 7 32-bit
  •  Internet Explorer 8 32-bit
  •  Firefox 3.x 32-bit
Level 2 Internet browsers options:
  • Internet Explorer 7 64-bit
  • Internet Explorer 8 64-bit
  • Firefox 3.x on non Windows operating system
  • Safari 3.x
I am not sure what is the difference been Level 1 and Level 2 support, but as long as both IE 7/8 and Firefox are included, I am good to go!

Friday, October 02, 2009

SharePoint IE 8 Popup Issue

Editing the SharePoint pages through the browser started throwing a pop-up “Are you sure you want to navigate away from this page?” The pop up will be shown after around 30 seconds, making the page editing slower and frustrating. This popup started showing up after I upgraded to IE8.





To remove the popup, you need to remove the body onUnload event handler. Sample code snippet to do the same:

<script type="text/javascript">
_spBodyOnLoadFunctionNames.push("UnloadHandler");

function UnloadHandler()
{
document.body.onUnload = "";
}
</script>

You can reduce the code snipped to one line by adding this to the bottom you’re your master page, just before HTML closing tag.

document.body.onUnload = "";


However, _spBodyOnLoadFunctionNames.push() is the preffered way to call your JavaScript function on client side page load.


Other option is to go change your IE settings and disable Enable native XMLHTTP support.

Tool->Internet Options->Advanced and disable ‘Enable native XMLHTTP support’


The JavaScript workaround will fix issue for all the users, the IE settings need to be done on every user’s machine trying to edit the page.

Saturday, September 26, 2009

Column Level Permissions in MOSS 2007

SharePoint 2007 supports customizing security only to the level of row /item level. If you need column level security, SharePoint 2007 does not provide support for the same.


A work around is to set the column as hidden and read-only, preventing it from being displayed in New and Edit forms. Please note that this is not 100% secure and there are ways to update the values of the hidden columns. SharePoint allows the values for such read only columns to be updated by calling the list web service or through SharePoint Designer Workflows.

The requirement for our intranet portal was that users should not be able to manipulate a particular column through the UI. The security risk was considered acceptable.

The read only property is not exposed through the UI and needs to be set using the object model or calling the UpdateList method of lists.asmx web service.

Sample Code using lists.asmx:

var listService = new ListsWebService.Lists();
listService.Url = "http://vbnbred123/_vti_bin/lists.asmx";
listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
string listName = "LeaveRequest";
string columnName = "LeaveStatus";

XmlDocument xmlDoc = new XmlDocument();
XmlNode updateNode = xmlDoc.CreateNode(XmlNodeType.Element, "Fields", "");
StringBuilder innerXMLNode = new StringBuilder("<Method ID='1'><Field ReadOnly='True' ShowInEditForm = 'FALSE' ShowInDisplayForm = 'True' ShowInFileDlg = 'FALSE' ShowInListSettings = 'True' ShowInNewForm ='FALSE' ShowInVersionHistory = 'FALSE' ShowInViewForms = 'TRUE' Type='Text' Name='");

innerXMLNode.Append(columnName);
innerXMLNode.Append("' DisplayName='");
innerXMLNode.Append(columnName);
innerXMLNode.Append("'/></Method>");
updateNode.InnerXml = innerXMLNode.ToString();

listService.UpdateList(listName, null, null, updateNode, null, null);

The read only column values can be updated through the workflow, and I created a workflow using SharePoint Designer for my requirements.

I hope SharePoint 2010 provides this out of box and this work around is not needed.

Monday, August 10, 2009

MOSS Advanced Search Queries

We recently had to determine the search queries fired when one used the OOB SharePoint Advanced Search Web Part. This was while working on an implementation of faceted search results, where we were getting different count of search results for Faceted and Advanced Search. The only way to make the results match was make both the web parts fire the same queries, and have similar settings for Duplicates, Noise words and stemming. First I will tell you the queries, and then I will talk about how did I extract them. Searching for my company name “MAQ Software” and selecting “MyCustomScope” forms the queries as:


All of these words:
SELECT WorkId, Rank, Title, Author, Size, Path, Description, Write, SiteName, CollapsingStatus, HitHighlightedSummary, HitHighlightedProperties, ContentClass, IsDocument, PictureThumbnailURL from scope() where freetext(defaultproperties,'+MAQ +Software') And ("scope" = 'MyCustomScope' Or "scope" = 'MyCustomScope')

The exact phrase:
SELECT WorkId, Rank, Title, Author, Size, Path, Description, Write, SiteName, CollapsingStatus, HitHighlightedSummary, HitHighlightedProperties, ContentClass, IsDocument, PictureThumbnailURL from scope() where freetext(defaultproperties,'+"MAQ Software"') And ("scope" = 'MyCustomScope' Or "scope" = 'MyCustomScope')


Any of these words:
SELECT WorkId, Rank, Title, Author, Size, Path, Description, Write, SiteName, CollapsingStatus, HitHighlightedSummary, HitHighlightedProperties, ContentClass, IsDocument, PictureThumbnailURL from scope() where freetext(defaultproperties,'MAQ Software') And ("scope" = 'MyCustomScope' Or "scope" = 'MyCustomScope')


None of these words:
SELECT WorkId, Rank, Title, Author, Size, Path, Description, Write, SiteName, CollapsingStatus, HitHighlightedSummary, HitHighlightedProperties, ContentClass, IsDocument, PictureThumbnailURL from scope() where freetext(defaultproperties,'-MAQ -Software') And ("scope" = 'MyCustomScope' Or "scope" = 'MyCustomScope')

I won’t go into the details of freetext clause or the significance of “+” or “-”sign in this blog. There are other articles on the net which describe the same in great detail.

To extract the queries, I started using Lutz .NET Refelctor and digging into the CoreResultsWebPart, which is found in the assembly Microsoft.Office.Server.Search. The CoreResultsWebPart class is a lazy guy, and relies on Microsoft.Office.Server.Search.WebControls.SearchResultHiddenObject to do most of the work. On closer study of the SearchResultHiddenObject class methods and fields, it can be seen that after composition, the search query gets saved in the field _fullTextQuery

I decided to create a custom web part, which inherits from CoreResultsWebPart, and read the query formed. However, the authors of SearchResultHiddenObject decided to make the class internal and this complicated things a bit. On trying to create an object reference of SearchResultHiddenObject, it gave the expected error message “SearchResultHiddenObject is inaccessible due to its protection level”. Object oriented boundaries can be broken and private and internal fields accessed using .NET reflection. That is what I did to get the above queries.

The approach is similar to the one described in Corey Roth’s blog, but you should write your code in the OnPreRender event. The query is not fully composed when other events earlier in the web part lifecycle are called.


Same logic can be used to find the queries fired by basic or people search, and you can give it a try.