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.

What’s Wrong with SharePoint?

So, I am watching Twitter updates go by (as I always do, even on a Saturday night), including my search that shows me all the tweets with “sharepoint” in them. As anyone knows who watches any amount of SharePoint commentary go by, there is a fairly constant flow of comments of the “SharePoint sucks” variety.

So this evening this led me to ask the question “What is wrong with SharePoint?” No, I do not mean I want a list of every nit picking, annoying little defect – every platform has defects and annoyances. I also do not want to know why SharePoint is note good for everything – no platform is good for everything. I also do not give a crap if your opinion is “it comes from Microsoft therefore it MUST suck” – it that is as deep as your analysis can go, well, you’re a moron.

What I want to see from SOMEONE is an intelligent, well thought out description of why SharePoint sucks. Why is it a bad choice for anything? Why should you perform an exorcism on all servers running any version of SharePoint?

I did a web search (notice I did not say “google” – contrary to popular usage, google is not a verb) for “what is wrong with SharePoint?” The only relevant results I found on either Google or Bing were written in 2005 or before, and hence are not particularly relevant at this point. For example, the post Five Things Wrong with SharePoint from back in 2005 tries to talk about what is actually wrong  with SharePoint. Even though I disagree with a lot of what it says, I will not refute it since it is so old.

So – if SharePoint is so bad…if all the otherwise intelligent people implementing solutions over SharePoint are wrong – where the heck are the statements as to what is wrong with it. So tell me – WHAT IS WRONG WITH SHAREPOINT? I really want to know, and to share it with others.

Working with Association Data in MOSS Workflows

I received a couple of comments in response to me previous post on Custom Association and Custom Initiation forms regarding how to use the Association and Initiation data collected, from within the workflow code. I had answered in my responses that you just access the AssociationData and InitiationData members of the WorkflowProperties, which return the data as XML strings. You then just work with that XML as required.

Here I will present some sample code for actually working with the XML coming from the custom AssociationData.

First, I would like to step back though and look at designing the Association Data. Typically when working with any InfoPath form, I start from the data side, and develop an XML Schema for the data (ideally, this is done as part of the overall design of the solution being developed, and includes all of the data design for the solution). The code snippet below shows the schema I developed for this example.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://t4g.com/TestSchema.xsd"
           elementFormDefault="qualified"
           xmlns="http://t4g.com/TestSchema.xsd"
           xmlns:mstns="http://t4g.com/TestSchema.xsd"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
   <xs:element name="AssociationInitiationData" type="AssociationInitiationDataType" />
   <xs:complexType name="AssociationInitiationDataType">
      <xs:sequence>
         <xs:element name="TaskDescription" type="xs:string" />
         <xs:element name="AssignTo" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
</xs:schema>

Note that this schema represents both the Association Data structure, as well as the Initiation Data. It is necessary for these two to share a schema and namespace, though the Association form need not populate all of the fields.

A Custom Association Form can then be developed in InfoPath based upon this schema, and deployed as described in my previous post.

Now, how do we access this Association Data from within our workflow?

I implemented a simple serializable class matching the schema, as shown below.

[Serializable()]
public class AssociationData
{
   private String _TaskDescription;
   private String _AssignTo;

   public String TaskDescription
   {
      get
      {
         return this._TaskDescription;
      }
      set
      {
         this._TaskDescription = value;
      }
   }

   public String AssignTo
   {
      get
      {
         return this._AssignTo;
      }

      set
      {
         this._AssignTo = value;
      }
   }
}

I also implemented a helper class (creatively named) to support loading the Association Data into this class (note that this helper handles both the Initiation and Association data):

public class Helper
{
   public static InitiationData DeserializeInitiationData(string xmlString)
   {
      using (MemoryStream stream =
         new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
      {
         XmlSerializer serializer =
            new XmlSerializer(typeof(InitiationData), "http://t4g.com/TestSchema.xsd");
            InitiationData data = (InitiationData)serializer.Deserialize(stream);
            return data;
      }
   }

   public static AssociationData DeserializeAssociationData(string xmlString)
   {
      using (MemoryStream stream =
         new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
      {
         XmlSerializer serializer = new XmlSerializer(typeof(AssociationData), "http://t4g.com/TestSchema.xsd");
         AssociationData data = (AssociationData)serializer.Deserialize(stream);
         return data;
       }
   }
}

Given these two classes, it is then simple to access the Association Data from within the workflow. For example, add a private member to the workflow class:

private AssociationData _associationData;

Then from within the onWorkflowActivated activity, add the following code:

String AssociationDataXml = workflowProperties.AssociationData;
_associationData = Helper.DeserializeAssociationData(AssociationDataXml);

The association data can then be accessed from within our _associationData object as required. The Schema, and the AssociationData class definition, can be modified as required to add additional fields.

I was considering another post about doing the same thing for InitiationData, but it works exactly the same way. So unless someone really insists, I will not bother.

Coming soon…MOSS Workflow Examples – Custom Task Forms (using InfoPath)

The next post in this series will be coming soon, I hope – maybe the end of April.

UPDATE: Still working on this – billable work is getting in the way 🙂 I am also working on doing the next one as a webcast rather than a long text tutorial. I am curious, what do you think is the best approach to this, text or video?

 

MOSS Workflow Examples – Custom Initiation/Instantiation Form (using InfoPath)

Previously, I posted a guide to creating and deploying a very simple custom Association form for a MOSS workflow. This time, I will walk through the steps to create a custom Initiation form, and also a bit of detail on consuming the data from the Initiation form from your workflow code. To reiterate what I said in the Association form walkthrough, what I am creating here is not a form you would use in a real workflow – the intent is to demonstrate the process with as much noise and detail stripped away as possible.
As I describe in my other post, the Association form is displayed when you connect your Workflow Template to a document/form library, list, or content type (the action known as creating an association). The Initiation form is displayed when the user actual starts or instantiates the workflow on an item in a list or document library. The intent is to collect startup information for the workflow. The information collected by the Instantiation form may be the same as on the Association form (allowing the user to override the defaults) or it may be completely different information. Have a look at  http://msdn.microsoft.com/en-us/library/ms481192.aspx if you would like to see Microsoft’s definitions.
Before we start, have a look at my previous post describing my base environment for creating these examples.
1) Create a new site
I used a new web application, and a new site collection created using the Team Site template. I named my site InitiationFormDemo;
2) Create Form Library
On this new site, create a Form Library (which I named Workflow Form Library);
3) Create Task List
Also create a new Task List. I called mine Workflow Tasks. At this point, your site home page should look something like the picture below.
Initiation Form Demo Site
4) Create Workflow Project
Launch Visual Studio 2008. Create a new project. Expand the C# project tree, select Workflow, and select the SharePoint 2007 Sequential Workflow. Name the project “MyWorkflow”. The create project dialog should look like the picture below.
Create Workflow Project
5) Set the properties for the project as shown below
Workflow Project Settings 1
Workflow Project Settings 2
Workflow Project Settings 3
6) Finish Creating Workflow Project
Click finish. Normally, we would change the workflow name in the project, add some activities, some code, etc., but this is not necessary for this example. The project should look something like this.
Workflow Project
7) Create Custom Initiation Form in InfoPath
Now we will create the InfoPath Initiation Form. Launch InfoPath and select Design a Form Template. Select the settings as shown below (Form Template, Blank, Enable browser-compatible features only).
InfoPath 1
8 ) Design the Custom Initiation Form – Create Data Source for Submission
In the InfoPath Designer, select Tools | Data Connections… and click the Add button. Create the new data connection as shown in the following pictures.
InfoPath 2
InfoPath 3
InfoPath 4
Click Finish and Close to get back to the main InfoPath window.
9) Create a Custom Field for the Form
In the Task Pane, under Design Tasks, click on Data Source. Right click on myFields, and select Add to add a new field to the schema. Create a new field as shown below, and click Ok.
InfoPath 5
10) Add the Custom Field to the Form
Drag and drop the My Setting field onto the design surface, to create label and text box for it. Also add a Button control, and change its label to “Submit”. Your form should look something like the picture below.
InfoPath 6
11) Add Logic to the Submit Button
Double click on your Submit button to display the Button Properties dialog. Click on the Rules… button, and click Add and then Add Action. Select options as shown below, and click Ok.
InfoPath 7
Click Add Action again, and set the options as shown below, and click Ok.
InfoPath 8
You should now have two actions, as shown below.
InfoPath 9
12) Set Form Security Level
Finally, we must set the form trust to Domain. Select Tools | Form Options…, and select Security and Trust. Unselect the checkbox Automatically determine security level (recommended), and click the Domain radio button, as shown below, and click Ok.
InfoPath 10
13) Save the Form Template
Save the form to disk (File | Save). You can save it anywhere you want, as long as it is not your Visual Studio project folder. I just save mine to a Forms folder in My Documents. Name the form MyInitiationForm.xsn for this example (in practice you can name it whatever makes sense).
14) Publish the Form Template
Now we want to publish the form. This did not entirely make sense to me, but when you select File | Publish…, on the first page of the publish dialog we will select To a Network Location even though we will actually publish it to our Visual Studio workflow project folder.
Publish 1
Click Next, and then browse to the location where you will publish the form. In this case, we want to publish to your workflow project folder, as shown.
Publish 2
Type a name for your form (I used MyInitiationForm.xsn), click Ok, and Next. On the next form, clear the text box and click Next (this is important, the form will not work if you do not clear that text box!)
Publish 3
When you click Next, a warning will pop up, as shown below. Click Ok to continue.
Publish 4
Click Publish and Close, and then exit InfoPath.
15) Retrieve Form ID to Use in Workflow Project
In Windows Explorer, navigate to your workflow project folder, right click on the InfoPath form you just published there, and select Design. When the form opens in design mode, select File | Properties… to display the properties dialog shown below.
Get Form ID
Select the ID as shown, and copy it to the clipboard. Click Ok and exit InfoPath.
16) Modify Workflow Project to Reference Custom Initiation Form
Go back to Visual Studio 2008, and open you workflow project if it is not still open. Open the workflow.xml file. The default file looks like this:
<?xml version="1.0" encoding="utf-8" ?>

<!-- Customize the text in square brackets.
     Remove brackets when filling in, e.g.
     Name="[NAME]" ==> Name="MyWorkflow"
 -->

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Workflow Name="MyWorkflow"
             Description="My SharePoint Workflow"
             Id="0d94af3a-45e7-4035-b351-9a10fc41018d"
             CodeBesideClass="MyWorkflow.Workflow1"
             CodeBesideAssembly="MyWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=96c40524715e44e9">

      <Categories/>
      <MetaData>
         <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
         <!--<Association_FormURN>[URN FOR ASSOCIATION FORM]</Association_FormURN>
         <Instantiation_FormURN>[URN FOR INSTANTIATION FORM]</Instantiation_FormURN>
         <Task0_FormURN>[URN FOR TASK (type 0) FORM]</Task0_FormURN>
         <Task1_FormURN>[URN FOR TASK (type 1) FORM]</Task1_FormURN>-->
         <!-- Modification forms: create a unique guid for each modification form -->
         <!--
         <Modification_[UNIQUE GUID]_FormURN>[URN FOR MODIFICATION FORM]</Modification_[UNIQUE GUID]_FormURN>
         <Modification_[UNIQUE GUID]_Name>[NAME OF MODIFICATION TO BE DISPLAYED AS A LINK ON WORKFLOW STATUS PAGE</Modification_[UNIQUE GUID]_Name>
         -->
         <StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>
      </MetaData>
   </Workflow>
</Elements>
Paste the ID from your InfoPath form properties into the <Instantiation_FormURN> element, and uncomment the element (be careful that the other commented out elements stay that way – or delete the ones you are not using as I did):
<Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:MyInitiationForm:-myXSD-2009-04-06T02-58-49</Instantiation_FormURN>
Of course, your actual URN will be different than mine.
Add the following new attribute to the <Workflow> element:
InstantiationUrl="_layouts/IniWrkflIP.aspx">
Your workflow.xml file should now look something like this:
<?xml version="1.0" encoding="utf-8" ?>
<!-- Customize the text in square brackets.
     Remove brackets when filling in, e.g.
     Name="[NAME]" ==> Name="MyWorkflow"
-->
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Workflow Name="MyWorkflow"
             Description="My SharePoint Workflow"
             Id="0d94af3a-45e7-4035-b351-9a10fc41018d"
             CodeBesideClass="MyWorkflow.Workflow1"
             CodeBesideAssembly="MyWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=96c40524715e44e9"
             InstantiationUrl="_layouts/IniWrkflIP.aspx">
      <Categories/>
      <MetaData>
         <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
         <Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:MyInitiationForm:-myXSD-2009-04-06T02-58-49</Instantiation_FormURN>
         <StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>
      </MetaData>
   </Workflow>
</Elements>
Save the file and close it.
17) Make Sure the Custom Initiation Form will get Copied With the Workflow Feature
Next, open the feature.xml file. It will look something like
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="15fdd97f-db32-44c1-96cc-cab49acecd36"
         Title="MyWorkflow feature"
         Description="My SharePoint Workflow Feature"
         Version="12.0.0.0"
         Scope="Site"
         ReceiverAssembly="Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
         ReceiverClass="Microsoft.Office.Workflow.Feature.WorkflowFeatureReceiver"
         xmlns="http://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
      <ElementManifest Location="workflow.xml" />
   </ElementManifests>
   <Properties>
      <Property Key="GloballyAvailable" Value="true" />
      <!-- Value for RegisterForms key indicates the path to the forms relative to feature file location -->
      <!-- if you don't have forms, use *.xsn -->
      <Property Key="RegisterForms" Value="*.xsn" />
   </Properties>
</Feature>
Find the <ElementManifests> tag, and under that, add a new <ElementFile> element inside it as shown:
<ElementManifests>
   <ElementManifest Location="workflow.xml" />
   <ElementFile Location="MyInitiationForm.xsn"/>
</ElementManifests>
Save the file and close it.
18 ) Rebuild your workflow solution, and deploy it.
19) Test it Out
Back in IE, navigate to your form library. Since I’ve not created a custom association form in this example, you can create the association using the default form (if you have set up your project to auto-associate, you will not need to do this manually).
Since we want to initiate a workflow, first we need to add a document to the library. I just clicked upload and selected a random file from my desktop. Hover over the file you uploaded and left-click to bring up the context menu. Select Workflow from the menu. Then click on MyWorkflow to start the workflow. This should bring up your custom instantiation form as shown below.
Start Workflow
Enter some text, and click Submit. You will see an animation showing that MOSS is working, and then you will be brought back to the Form Library page. The status of your workflow should show as complete, since the workflow does not actually do anything.
20) Accessing the Initiation Form data in your workflow
I will now quickly show how to access your initiation data from your workflow. We will simple pull out the string entered and log it.
Open your workflow project in Visual Studio, and open your workflow in design view. Add a new logToHistoryListActivity as shown below, and set the HistoryDescription property as shown (set it to a String Field named HistoryDescription in your workflow).
Add LogToHistoryList LogToHistoryList Properties
Right click your logToHistoryListActivity and select Generate Handlers. In the event handler, add code as show below:
public String HistoryDescription;
private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e)
{
      String MySettingValue = workflowProperties.InitiationData;
      HistoryDescription = "Initiation String Entered: " + MySettingValue;
}
Rebuild and deploy your workflow, and execute it as in Step 19. Click on the Completed link as shown below.
In the Workflow Status you will now see a history event as shown below, and the initiation string is shown as an XML string, with a <MySetting> element and the string I entered. To use this data in a workflow, you would parse the XML and go from there (or generate a class from the schema and load the XML into that).
Workflow Status
Well, there it is. A custom Initiation form using InfoPath.
Next time – custom Task forms!