Creating Custom Web Part Properties

The Microsoft SharePoint 2010 Web Part framework enables users to configure a Web Part through Web Part properties. A default user interface (UI) is given for each Web Part property that is exposed to the user in the Edit Tool pane of the Web Part. For example, a property of type String is rendered as a text box, and an Enum is rendered as a drop-down list box.

This default rendering by the framework does not allow for much customization because the user cannot get a handle to the controls that are rendered. For example, it has the following limitations:

  • Control over UI: Numeric and string types are rendered as text boxes, enumeration types are rendered as a drop-down list box, and Boolean types are rendered as check boxes. So, you cannot show an enumeration type as radio buttons instead of a drop-down list box.
  • Events: Events that are raised by the controls cannot be handled; for example, you cannot enable or disable a drop-down list based on selecting a check box.
  • Validation: If user input has to be validated, the framework does not provide a way to easily attach a Microsoft ASP.NET validation control to the input control that is generated. For example, you cannot validate a string input for a valid email address through an ASP.NET RegEx validation control.

You can overcome these limitations by using custom editor parts. With custom editor parts, you can offer users functionality that can be achieved through ASP.NET user controls. A Web Part can implement custom editor parts that can be loaded when the Web Part is in edit mode, expose a custom UI, handle events, and validate inputs. A Web Part can have more than one custom editor part associated with it.

SharePoint 2010 Visual Web Parts contain a set of properties that we can use to control its appearance and behavior during runtime. Sometimes we might need to add our own properties to a Web Part so that we can implement more generalized controls, which can be plugged-in to different pages based on a mode or a category.
 
If I just add a Visual Web Part with the default name “VisualWebPart1” to my SharePoint project, I will get a User Control (called “VisualWebPart1UserControl.ascx”) and a Web Part class (called “VisualWebPart1.cs”) inheriting from the WebPart base class. This VisualWebPart1.cs is used to load the User Control as well as to set personalization settings. So I have to add my custom property to the VisualWebPart1.cs.
 
So the basic steps to add a custom property are;
  1. Add a custom property in “VisualWebPart1.cs” Web Part class
  2. Make above custom property visible to “VisualWebPart1UserControl.ascx” User Control
  3. Access custom property from the User Control

 Code to follow or go here for a more detailed explanation:

http://blog.concurrency.com/sharepoint/create-a-custom-web-part-for-sharepoint-2010/

Catch 22 with SPD workflow and checking in documents

I recently had to build a workflow in SharePoint Designer to model a fairly lengthy approval process for policy documents involving multiple stages of review, each of which has to be passed before the draft document moves to the next review stage. The workflow itself was quite long but essentially boiled down to a series of repeated steps. Each step involved assigning a task to a reviewer (or reviewers) and then updating the status of the document to show what stage it was at. The Policies document library has enforced check in/out, version control, and content approval all turned on. I also needed a field called Review Stage to show what stage the document was at – that was a simple choice field with 7 different stages.

Version History

The obvious thing was to add the Review Stage field to the document library.  After some playing around with the workflow, however, I decided to do things a more complex way.  I created a new list called Document Review Stages with two fields, one was the choice field Review Stage and the other was a number field called DocumentID.  For each policy document in the document library, there is a corresponding entry in the Policy Review Stages list.  The DocumentID holds the ID (the built-in column that SharePoint populates automatically) of the policy document.  In other words, I effectively created a one-to-one relationship between the Policies document library and the Policy Review Stages list.  Of course, this being SharePoint and not a full-blown database, this isn’t a proper relationship – there’s no enforced referential integrity, no cascading updates, etc.  But the basic principle is the same.

So why did I do it in this convoluted way?  Well because the Policies document library has enforced check-in/out and major/minor version control.  So suppose I had the Review Stage column on the Policies document library itself.  That would mean any change to the document, even just changing its metadata, would create a new version.   And that means that the workflow, if it wants to progress the document to the next review stage, would have to first check out the document, then set the Review Stage field, then check the document back in again.  And you’d then have 2 versions of that document, both exactly the same in content, but with different Review Stage metadata values.  This would result in a confusing version history for each document, with some genuinely different versions of the document (edited by different reviewers) but also many identical copies of each document created automatically by the workflow as it moves the document through the review stages.  By moving the  Review Stage column to a different list, the workflow can update the Review Stage field without creating a fresh copy of the document in the version history. That makes the version history much cleaner and more readable.

Approval Catch-22

This being a SharePoint Designer workflow, not a Visual Studio one, I had to attach it to the Policies document library.  I got the workflow to find the Policy Review Stages list item related to its corresponding policy document, and update the Review Stage column on the list.  So far so good, but then right at the end of the workflow, the last step was to make the document go live by setting its approval status to be “Approved”.  There’s a special workflow action to do just that, so it seems easy enough.  But there’s a catch.  If you want to make the document Approved status, you have to change it, and the workflow complains if you try to change it without first checking it out.  OK, so you change your workflow to check the document out first, and then approve it.  But now the workflow complains because you can’t approve a document that is checked out.  Catch-22!

So how do you get round this?  Well you can use the Start Another Workflow action to start the normal Approval workflow on the document.  The built-in Approval workflow can work with a document that’s not checked out.  So you end your workflow early, before the final approval task is allocated, and hand off control to a standard Approval workflow to manage the final approval step.

PerfomancePoint Dashboard Designer “Code blocks are not allowed in this file”

If you are configuring PerformancePoint in SharePoint 2010, and you are attempting to launch the Dashboard Designer ClickOnce application from the Business Intelligence Center site you have created, you may encounter this error. Some books and blog posts on the subject of configuring and running PerformancePoint services do not seem to touch on this – SharePoint by default, does not allow in-page code.

To get around this, you will need to modify the web.config file for the web application in which PerformancePoint lives, by inserting the following code in the <SharePoint><SafeControls><PageParserPaths> section as shown below.

 

<SharePoint>
  <SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">
     <PageParserPaths>
       <PageParserPath VirtualPath="/BICenter/Pages/ppssample.aspx" CompilationMode="Always" AllowServerSideScript="true" />
     </PageParserPaths>
  </SafeMode>
</SharePoint>

Where the VirtualPath listed above is the relative URL to the ppsample.aspx page within your BI Center.

Why Oh Why doesnt my Performance Point Designer work??

Opening Dashboard Designer from a PerformancePoint item in a SharePoint list

Issue:   You might be unable to open Dashboard Designer from a PerformancePoint item, such as a report, scorecard, or data connection in a SharePoint list.

Summary:   When you try open Dashboard Designer from a PerformancePoint item that is located in either the Data Connections or the PerformancePoint Content list, you might receive an error message instead.

Resolution:   We recommend that you open Dashboard Designer from the PerformancePoint site template for the first time.

To open Dashboard Designer from the PerformancePoint site template

  1. In the Business Intelligence Center, click a section, such as Monitor Key Performance, Build and Share Reports, or Create Dashboards. More information about each area is displayed in the center pane:
  2. Click the Start using PerformancePoint Services link. The PerformancePoint site template opens.
  3. Click Run Dashboard Designer. If you have the necessary permissions assigned to you in SharePoint Server, Dashboard Designer will install and open.

Using the Safari Web browser to start Dashboard Designer

Issue:   When you attempt to open Dashboard Designer from the PerformancePoint site template and you are using the Safari Web browser, Dashboard Designer does not start.

Resolution:   We recommend that you use Internet Explorer to start Dashboard Designer for the first time. After that, you can open Dashboard Designer by using the Start menu. (Click the Start button, point to All Programs, point to SharePoint, and then click PerformancePoint Dashboard Designer.)

Using the Mozilla Firefox Web browser to start Dashboard Designer

Issue:   When you attempt to open Dashboard Designer, you might encounter an error message.

Message:   The error message indicates that you cannot download the application, and that the application is missing required files. This can occur if Microsoft .NET Framework Assistant 1.1 is not installed on your computer.

Resolution:   Download and install Microsoft .NET Framework Assistant 1.1. For more information, see Microsoft .NET Framework Version 1.1 Redistributable Package (http://go.microsoft.com/?linkid=9763247).

Content Organiser and Workflow Fix

I have been looking at using the new Content Organizer feature in SharePoint 2010. The idea being that when people upload or ‘Send To’ a document center, the document is routed to the correct location.

When I enable the Content Organizer feature on my site, the ‘Drop Off’ library is created.

I then create a rule to route the document to the ‘Documents’ library. I don’t want the document to be published and visible to all users until it has been approved. So I create a simple Workflow to do approval which should start when the document is created.

Unfortunately, the workflow never starts automatically once Content Organizer has been enabled.

I had a look at the Content Organizer code with Reflector, and it seems to be executing a SystemUpdate after it has moved the document to the correct location. I assume it is running this as one of the service accounts. (I have not checked which one).

When I look at the ULS logs in more detail, I see the following exception is occurring when I upload a document.

“Declarative workflows cannot automatically start if the triggering action was performed by System Account. Canceling workflow auto-start.”

I tried submitting the document as a user other than System Account, but the error persisted.

So I decided to look at starting the workflow programmatically. I created an Event Receiver is Visual Studio 2010.

I found this post from Tobias Zimmergren with some sample code to programmatically start a workflow.

http://www.zimmergren.net/archive/2009/01/25/starting-a-sharepoint-workflow-from-code-event-receiver.aspx

I overrode the ItemAdded event as follows:

public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
//SPListItem item = properties.ListItem;
//item[“Title”] = ” ” + item[“Title”] + ” – added ” + DateTime.Now;
//item.Update();

if (properties.ListItem.ParentList.TemplateFeatureId==new Guid(“00bfea71-e717-4e80-aa17-d0c71b360101”))
{
SPWorkflowManager wfManager = properties.ListItem.ParentList.ParentWeb.Site.WorkflowManager;
SPWorkflowAssociationCollection wfassociationCollection = properties.ListItem.ParentList.WorkflowAssociations;
foreach (SPWorkflowAssociation wfAssociation in wfassociationCollection)
{

if (wfAssociation.BaseId == new Guid(“8ad4d8f0-93a7-4941-9657-cf3706f00409”))
{
wfManager.StartWorkflow(properties.ListItem, wfAssociation, wfAssociation.AssociationData, true);
break;
}

}
}
}

I got the baseid for the WorkflowAssociation using SharePoint Manager:

I run the event receiver by pressing F5 in Visual Studio and watch the behaviour.

When I upload the document, the content organizer routes the document to the folder in the library and the workflow starts.

I expect to spend some more time refining the code for the eventreceiver to make sure it only executes under the right circumstances, but thought I would share in case anyone else is experiencing the same issue.

References

http://sharepoint-sandbox.com/index.php?/SharePoint-2010/Content-Management/tip-88-sharepoint-2010-content-organizer-execution-order.html?directory=14

http://blog.ozippy.com/2010/06/starting-workflow-when-content.html