SharePoint Notifications using JGrowl

Slick little bit of code, full of AJAX-y goodness!

SharePoint 2010 Popup Notifications

http://zieglers.wordpress.com/2011/07/28/jgrowl-notifications-for-sharepoint-2010-part-1/

http://zieglers.wordpress.com/2011/08/22/jgrowl-notifications-for-sharepoint-2010-%E2%80%93-part-2/

Advertisements

Make Your SharePoint 2010 Master Page Extensible with Delegate Controls

I have been playing a lot the last little while with SharePoint 2010 Delegate Controls. I have known about them for a ling time, but have never really delved into them all that much.

Most of the examples I have looked at, and the usage ideas I have seen, involve using the existing delegate controls in V4.master to do things like:

  • Modify the Welcome Menu
  • Customize the Global Navigation
  • Add useful code to the page header

Last week, I used a delegate control for something a little different.

For a project I am working on, the client wanted some functionality displayed just below the Quick Launch, on every page in the site collection. I know there are lots of ways to do this (put a user control on the master page, put a web part on the master page, or just put links on the master page, since that’s all the content was in this case).

But then I thought of a little bit more elegant (to me) solution. Rather than explicitly putting the content on the master page, I added a delegate control of my own to the page, and placed it just below the Quick Launch, as shown below.

image

Several things to note here:

  • I gave it a ControlID specific to my application;
  • I set AllowMultipleControls to true, which will be useful later
  • I included default content in the <Template_Controls> element, so that I could see it change when I activate a Feature with an appropriate control.
  • Next, I implemented a Feature in Visual Studio 2010, with a control to replace the default content. The details of how to do this are covered in other places (such as here), but to summarize:
  • I created an empty Visual Studio 2010 project;
  • I created a user control inside the project (this automatically mapped the ControlTemplates folder for me). It is a very simple user control, and simply displays “Hello, Delegate!”
  • I created an appropriate elements.xml file to map my control to the Delegate Control’s ControlID.

So, here we see the how the delegate looks before I deploy my feature:

image

After I deploy my Feature, we see that the default content is replaced with the Feature’s control’s output:

image

But wait, there’s more! Remember that I set AllowMultipleControls to true? That allows me to deploy multiple features with controls that map to my ControlId, and instead of only displaying the one with the lowest Sequence attribute, it will stack them all in order of Sequence number, as shown below.

image

This means that I can add any number of  things to the area under the Quick Launch without further customizing the the Master Page.

Maybe I am just easily amused, but I thought that was pretty neat!

The source for this, including the master page, is available here.

Why are you still not focused on the business when implementing SharePoint?

Over the past week I have been reading a couple of recent SharePoint-related papers, and thought I would share some of my thoughts.

The first paper is entitled SharePoint – strategies and experiences from AIIM. This document presents the results of a survey of 624 AIIM members last spring regarding experiences and plans with SharePoint. I strongly recommend downloading and reading the entire report, as I do not intend to cover all of it in this post, only those items that seemed interesting to me (which is actually difficult, because there is a fair amount of interesting stuff in there!).

The findings I found most interesting were:

  • Lack of business-case justification for implementations
  • Governance challenges
  • Perceived ROI
  • Implementation challenges
  • The number of organizations planning to upgrade to SharePoint 2010
  • The ranking of most popular uses of SharePoint

For me, the most startling result in the report is

Half of SharePoint implementations went ahead with no business case being made to justify the
investment. Only 23% were required to make a financial justification. Where a business case was
made, improved collaboration and better knowledge sharing were the main benefits assessed.

Is it just me, or is this insane? As I said last year in my column Danger! Do not implement SharePoint in your Organization!, the focus of your SharePoint implementation should be solutions to real business problems, bringing real business value. A business case is not just something you do in order to get funding. It is something you do so you understand what functionality you are implementing and why. Not doing a business plan is setting the project up for failure, but for a failure you may never know about. After all, if you have nothing against which to measure success, how can you even know if you have failed, or at least failed to live up to potential? I guess I am optimistic, but I thought everyone understood this by now.

The second point is equally astonishing to me. While the first links I saw to the AIIM document had headlines implying some weakness in SharePoint governance was found (here for example), the real finding is that many of the organizations implementing SharePoint simply do not put appropriate governance in place. A great many organizations have a lack of definition of governance of features, sites or content.

Surprisingly, despite the lack of business case and governance, most of the organizations surveyed were happy with the ROI achieved (which is amazing if they had no definition of what they were trying to accomplish!). Only 9% said that the ROI was worse than expected. Then again, maybe this is just a reflection of having no real idea of what you expected the ROI to be.

The results also identified some of the challenges faced when implementing SharePoint. Among the key issues identified were:

  • Managing process change
  • Took longer than expected
  • User resistance to new UI
  • Technically more difficult than expected
  • Cost more than expected
  • Poor performance/infrastructure capability

All of these, in my opinion, are reflections of lack of planning and lack of business case. While many of these challenges are common even in the best of circumstances, a lack of a clear, business-focused vision and plan will invariably make them worse.

There were also a couple of positive results from the report (more than a couple, but 2 I will mention here).

The results indicated that 13% of the respondents are planning to upgrade to SharePoint 2010 almost immediately, while half are planning to within a year. I see this as positive, anyway.

It was also interesting to look at what SharePoint features are most popular in these organizations. While I always tend to think of SharePoint primarily as a portal platform, and a solution development platform (hey, I am a developer), the most popular usages found in the survey were:

  1. Collaboration
  2. Document management and file-share replacement
  3. Portals
  4. Intranets

These are just some of the points I found interesting in the report. Again, I strongly urge anyone looking at SharePoint to real the whole report.

SharePoint 2010 Workflow Example – Custom Association and Initiation Forms

A year of so ago I wrote a couple of posts on MOSS 2007 workflows, specifically around the creation of custom Association and Initiation forms using InfoPath. While neither of these tasks are really very difficult (once you have figured out how), I think most would agree that the whole process is a great deal more messy that it should be.

Now that we are near the release of SharePoint 2010 (it went RTM last week and ships May 12, for those who have not seen the 2 million other posts letting you know), I thought I would revisit these same activities in SharePoint 2010 to demonstrate the fact that the process is whole lot less messy.

(Note that I have not had time to do screen captures as I did in my previous examples. If you have trouble following what I have done, leave a comment and I will add the pictures in).

The first couple of steps are identical to the previous version:

1) Create a new site.

2) Create a new document library (make sure you add at least one document to the library for testing later).

Now things get a little different.

3) Run SharePoint Designer 2010, and open your site.

4) In the Site Objects list on the left hand side, select Workflows. You will see the list of workflows defined on the site, which at this point will just be built in workflows. You can edit these workflows (though I wouldn’t) or you can create a copy of one of them to serve as a starting point. In this example, however, we will start from scratch.

5) In the Ribbon you will see three choices for creating a new workflow:

  • A List Workflow: Creates a workflow associated with a specific list. These workflows can only be associated to one list, and cannot be re-used
  • A Reusable Workflow: Creates a workflow which is not pre-associated with a particular list. These workflows can be later associated with one or more lists or content types. They can also be exported as WSP packages and reused across multiple sites.
  • Site Workflows: Site workflows are not associated with a list or content type. They are initiated from the Site Actions menu, and their instances are not connected to list items.

In this example, we will create a Reusable Workflow. Give your workflow a name, a description if you want, and leave the Content Type selection at “All”, and click Ok.

6) You will now see the workflow editor in SharePoint Designer. The main canvas is where you design the logic of your workflow. Make sure your insertion point is in Step 1, and from the Action gallery of the Insert section of the Ribbon, select “Log to History List”. Click on “this message” in the design area, and enter text to be logged. I used “My Workflow Started”.

7) Now for the point of this example – we will create an Association and Initiation parameter. In the Ribbon, click on Initiation Form Parameters.

Click Add…, and define a new parameter. Mine is called “MyParameter”, is of type “Single Line of Text”, and will be shown on both the Association and Initiation forms (you can also have a parameter which is only shown on Association, or only shown on Initiation). Once you have defined your parameter, click Ok.

8 ) Now you can add a reference to your parameter to you “Log to History List” activity. Open the message to be logged, and click the ellipses (…) to display the string builder tool. Click Add or Change Lookup, and select “Workflow Variables and Parameters” as the Data Source. Then select your parameter in the “Field from Source” drop down, and select String as the “Return Field As” selection. Click Ok, and then Ok again.

9) Now we should be ready to test things. In the Ribbon, click Publish. This will make the workflow available in your site.

10) Navigate to your site in the browser, and open the document library you created for this example. At the top of the page, under Library Tools, select Library. On the far right side of the Ribbon, select the Workflow Settings drop down, and select Add a Workflow. Select your custom workflow from the list, give your workflow association a name, and leave all the other settings at the default values. Click Ok.

11) A custom association form will now be displayed, asking for your parameter. Enter a default value for the parameter (I used “Default Value”). Click Save.

12) Now return to your document library, and select one of your documents. From the menu for the document, select Workflows. On the Workflows page that is displayed, select your workflow. A custom initiation form is now displayed, asking for the parameter you defined. Enter a value and click Start.

13) You will now be taken back to your document library. Notice that the document you used for the test now has a column named for your workflow, and has a value there of Completed. Click on Completed to view the workflow status page. You should now see the status for this workflow instance, and at the bottom you should see your logged message, with the value you entered for the parameter in your Initiation form.

While this procedure has almost as many steps as the previous examples for MOSS 2007, it is obviously a lot less messy to create and access Association and Initiation parameters in SharePoint 2010. From here, you can go back to SharePoint Designer, from which you can see the actual form (.XSN) used for your workflow, and you can open it up and customize it in InfoPath.

Simple SharePoint 2010 + Silverlight + Client Object Model Example

NOTE: I updated this post today (Feb 7, 2011) to make the code snippets easier to work with. I tried very hard not to introduce any new typos as I did this, but if you see anything wonky, let me know (if somehthing is not working – think about typos FIRST!)!

This post will take you through a very simple example of using a Silverlight application in SharePoint 2010, using the new SharePoint 2010 Client Object Model. I will also show how to use the new SharePoint 2010 tools in Visual Studio 2010 to package the Silverlight application for deployment. Note that I will not be getting into the details of creating a flashy (no pun intended) UI in Silverlight – i will just create a very simple UI with a list box and a text box.

The Example is broken into 2 parts. The first will describe how to create a SharePoint 2010 solution which will deploy a Silverlight XAP file to SharePoint. The second part will introduce a simple Client Object Model solution in Silverlight.

Part 1 – Creating a SharePoint 2010 Solution to Deploy a Silverlight Application

1) Start with a Team Site in SharePoint 2010 (I am sure any other site type would work just as well).

2) Create a document library to store your Silverlight XAP file (I called mine Silverlight).

3) On the home page of the team site, add a SharePoint Silverlight web part as shown below:

Silverlight Web Part

Next, we will create the Visual Studio 2010 solution.

4) Create a new Visual Studio project, selecting the Empty SharePoint Project template (Visual C# | SharePoint | 2010 | Empty SharePoint Project). Name your solution SharePointSolutionDeployment. This will also add an empty SharePoint project in the solution. Make sure you point to the site you just set up for debugging. In addition, you have the option of creating a Sandbox or Farm solution – in general you should create a Sandbox solution unless you find you really need to do otherwise.

5) Next, add a Silverlight Application project (Visual C# | Silverlight | Silverlight Application) to the solution.  I named mine Simple Silverlight Application.

6) Change the background colour of the layout grid in the MainPage.xaml file. Double click MainPage.xaml to open it in design mode. and change the background colour of the grid to slate gray (or what ever you like – this is just to make it obvious when it shows up in SharePoint).

Now we will add the Module to the SharePointSolutionDeployment project, which will deploy our Silverlight XAP file to SharePoint.

7) Right click the SharePointSolutionDeployment and select Add | New Item…then select Visual C# | SharePoint 2010 | 2010 | Module. Name it Simple Silverlight Application Module

8) In the Solution Explorer, right click the Sample.txt file, and select Delete (note that it is also automatically deleted from the Elements.xml file).

9) Click on the Simple Silverlight Application Module, and observe the Properties display, as shown below:

Module 1

10) Click on the ellipses to edit the Project Output References collection, and click Add:

Module 2

11) Click the dropdown next to Project Name, and select Simple Silverlight Application. Then change the Deployment Type to ElementFile, and click OK:

Module 3

12) Now, open the Elements.xml from your Simple Silverlight Application Module and make the following changes:

13) In the Module element, add the attribute Url=”name of your document library” (use the name of the document library you created in Step 3).

14) Add the following File element inside the Module element:

<File Path="Simple Silverlight Application Module\Simple Silverlight Application.xap"
      URL="Simple Silverlight Application.xap"
      Type="GhostableInLibrary" />

15) Your Element.xml file should now look like:

<?xml version=1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Module Name="Simple Silverlight Application Module" Url="Silverlight">
      <File Path="Simple Silverlight Application Module\Simple Silverlight Application.xap"
            URL="Simple Silverlight Application.xap"
            Type="GhostableInLibrary" />
   </Module>
</Elements>

 

16) You should now be able to build and deploy your solution (under the Build menu).

17) Once you have deployed the solution, check your SharePoint site to verify that the XAP file was deployed to the Silverlight library.

18) Go to your site home page (or the page where you created your Silverlight web part), and configure the Silverlight web part to point to your XAP file. After saving the settings and saving the page, your Silverlight web part should look something like below (note that the rectangle is slate gray, as we set in step 3):

Part 1 Complete

Part 2 – Using the Client Object Model in the Simple Silverlight Application

In this step, we will modify the Simple Silverlight Application to use the SharePoint 2010 Client Object Model to access information regarding the lists on the site.

19) In the Simple Silverlight Application, add references to Microsoft.SharePoint.Client.Silverlight and Microsoft.SharePoint.Client.Silverlight.Runtime. You will have to browse to find these in the Add Reference dialog. They are located at C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin

20) Right-click App.xaml and select View Code.

21) Add the following using statements:

using Microsoft.SharePoint.Client;
using System.Threading;

 

22) Next add the following statement to the start of the Application_Startup method:

private void Application_Startup(object sender, StartupEventArgs e)
{
      ApplicationContext.Init(e.InitParams, SynchronizationContext.Current);
      this.RootVisual = new MainPage();
}

 

23) Now modify the MainPage.xaml design, adding a List Box and a Text Box as shown below. The List Box will be used to display a list of the lists on the site, and the Text Box will display some details regarding the list selected in the List Box.

<Grid x:Name="LayoutRoot" Background="SlateGray">
   <StackPanel Orientation="Horizontal" >
      <ListBox Name="lbLists" Width="300" Height="400" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="20,20,20,20" />
      <TextBox Name="txtDetails" Width="200" Height="400" TextWrapping="Wrap" />
   </StackPanel>
</Grid>

24) Right click MainPage.xaml and select View Code. the following using statement to MainPage.xaml.cs:

using Microsoft.SharePoint.Client;

25) Add two member variables as shown below:

private Microsoft.SharePoint.Client.Web _web;
private Microsoft.SharePoint.Client.List _list;

26) Add the following code to the MainPage constructor, below the InitializeComponent() call. Note the call to ExecuteQueryAsync – as this is Silverlight, the queries back tot he server need to be asynchronous.

ClientContext context = new ClientContext(ApplicationContext.Current.Url);

_web = context.Web;

context.Load(_web);
context.Load(_web.Lists);

context.ExecuteQueryAsync(new ClientRequestSucceededEventHandler(OnRequestSucceeded), new ClientRequestFailedEventHandler(OnRequestFailed));

27) Next, add the two callback routines from ExecuteQueryAsync, as shown below. In OnRequestSucceeded, the call to FillList is called on a separate thread. The OnRequestFailed method is just a stub.

private void OnRequestSucceeded(Object sender, ClientRequestSucceededEventArgs args)
{ // this is not called on the UI thread
      Dispatcher.BeginInvoke(FillList);
}

private void OnRequestFailed(Object sender, ClientRequestFailedEventArgs args)
{
}

28) Now, implement the FillList method:

private void FillList()
{
   lbLists.Items.Clear();
   lbLists.ItemsSource = _web.Lists;
   lbLists.DisplayMemberPath = "Title";
}

29) Build and deploy the solution. Refresh your page with the Silverlight web part. The List Box should now display a list of the Lists on your site, as shown below:

Lists

30) Next, we will add an event handler for the List Box selection changed, and to then retrieve the details for the selected list.

31) In the design view for MainPage.xaml, double click the list box to create a handler for the selection changed event. Add the following code to the event handler (again note the asynchronous call):

private void lbLists_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   using (ClientContext context = new ClientContext(ApplicationContext.Current.Url))
   {
      _list = context.Web.Lists.GetByTitle(((Microsoft.SharePoint.Client.List)lbLists.SelectedItem).Title);
      context.Load(_list);
      context.ExecuteQueryAsync(new ClientRequestSucceededEventHandler(OnListDetailsRequestSucceeded), null);
   }
}

32) Add the callback routine for the asynchronous query:

private void OnListDetailsRequestSucceeded(Object sender, ClientRequestSucceededEventArgs args)
{ // this is not called on the UI thread
   Dispatcher.BeginInvoke(ShowListDetails);
}

33) Finally, add the routine to display the list details in the Text Box:

private void ShowListDetails()
{
   string infoAboutList =
      string.Format("List Details:" + Environment.NewLine +
                         "Title: {0}" +
                         "Description: {1}" +
                         "Item Count: {2}" +
                         "Base Template: {3}" +
                         "Base Type: {4}" +
                         "Content Types Enabled?: {5}" +
                         "Hidden?: {6}",
                         _list.Title + Environment.NewLine,
                         _list.Description + Environment.NewLine,
                         _list.ItemCount + Environment.NewLine,
                         _list.BaseTemplate + Environment.NewLine,
                         _list.BaseType + Environment.NewLine,
                         _list.ContentTypesEnabled + Environment.NewLine,
                         _list.Hidden + Environment.NewLine);

   txtDetails.Text = infoAboutList;
}

34) Build and deploy the solution. Refresh your page with the Silverlight web part. As before, the List Box should now display a list of the Lists on your site. Select one of the lists, and the details for the list should be displayed in the Text Box, as shown below:

List Details

This has been a very simple introduction to creating and deploying a Silverlight application into SharePoint 2010, and then using the SharePoint 2010 Client Object Model to access list information and display it in Silverlight. This could be extended to query more information on the Lists, or information on other collections on the site, such as Content Types, or Workflow Templates. The Silverlight UI could also obviously be enhanced as well.