SPD custom workflow actions — string manipulation enhancements

About a week ago, I started up a codeplex project that provides a simple and reasonably generic method for adding custom action functions to SharePoit Designer workflow.  It’s described here: http://www.codeplex.com/spdwfextensions.  Beyond simply providing a framework, it also aims to provide a set of useful functions that will make SPD more useful/flexible/powerful. 

Here are the current planned features for version 1.0: https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=spdwfextensions&ReleaseId=8280

If anyone has any interest in this project, please leave a comment or start/add to a discussion here: http://www.codeplex.com/spdwfextensions/Thread/List.aspx

Here are the current set of functions that have been coded (though not fully tested as of 11/08/07):

Function Description (if not same as .Net function)
Num-entries() Returns the number "entries" in a string as per a specified delimiter. 

For example: Num-entries in a string "a,b,c" with delimiter "," = 3.

Entry() Returns the nth token in a string as per a specified delimiter. 
Length String.Length
Replace() String.Replace()
Contains() String.Contains()
Returns the word "true" or the word "false".
Substring(start) String.Substring(start)
Substring(start,end) String.Substring(start,end)
ToUpper() String.ToUpper()
ToLower() String.ToLower()
StartsWith() String.StartsWith()
Returns the word "true" or the word "false".
EndsWith() String.EndsWith()
Returns the word "true" or the word "false".

Quick & easy url Encoding desktop utility

I’ve been needing to url-encode some strings this week and slapped together a a little utility that I thought I’d put up on SkyDrive for the community.

Get the binary here: http://cid-1cc1edb3daa9b8aa.skydrive.live.com/self.aspx/SharePoint/WinUrlEncode.zip

Get the visual studio solution here: http://cid-1cc1edb3daa9b8aa.skydrive.live.com/self.aspx/SharePoint/WinUrlEncodeVS2005.zip

Here’s a screen shot:

image

Quick and easy: Embed a hyperlink into data view web part XSLT

UPDATE (01/17/08): This blog entry talks about more hyperlink XSL goodness: http://www.sharepointsecurity.com/blog/sharepoint/sharepoint-2007-development/rewriting-links-in-search-results-xslt.

Overview and Objective: I had created a simple bar chart to serve as component on a dashboard.  I’ll save the details on building charts for another post, but I did not invent that technique (nor the question mark, for that matter).  It turned out there was a bug in the chart and while I fixed that, I took the opportunity to convert some labels into hyperlinks that pointed at the underlying list behind the graph.  For example, there is a label with value "Hold".  I wanted to turn the label into a hyperlink so that the user could click on it and drill down to the specific entries in the list whose status value is "Hold".

Steps:

  1. Use visual studio for sharepoint-aware intellisense.
  2. Copy the DVWP’s XSLT into visual studio (create a blank project, add an XSL file to the project).
  3. Copy the link you want to use into the clipboard.
  4. Paste it into the right location in the XSL.
  5. Convert URL argument separators on the query string from "&" to "&"
  6. Url-encode individual arguments.
  7. Wrap that inside an <a href…> </a>

Example:

I have an URL:

http://[server]/[site]/Lists/Open%20Positions/AllItems.aspx?View={84EEA2F5-121B-40B7-946F-0FA704A1DAA1}&FilterField1=Recruiter&FilterValue1=Hold

I convert it into:

     <a href="Lists/Open%20Positions/AllItems.aspx?View=%7b84EEA2F5-121B-40B7-946F-
0FA704A1DAA1%7d&amp;FilterField1=Recruiter&amp;FilterValue1=Hold"> Hold: </a>

I have manually transformed the first argument from:

{84EEA2F5-121B-40B7-946F-0FA704A1DAA1}

to:

%7b84EEA2F5-121B-40B7-946F-0FA704A1DAA1%7d

(In this, the open brace transforms to %7b and the closing brace transforms to %7d)

The second and third arguments’ parameters ("FilterField1=Recruiter" and "FilterValue1=Hold" respectively) do not need to be url-encoded because they do not contain any unsafe characters.

Notes:

This technique should generally work anywhere you want to embed a hyperlink in XSLT where the hyperlink includes parameters on the URL such as:

http://[server]/[site]/Lists/Open%20Positions/AllItems.aspx?View={84EEA2F5-121B-40B7-946F-0FA704A1DAA1}&FilterField1=Recruiter&FilterValue1=Hold

I got the URL itself by accessing the custom list and manually filtering on the status column (labeled "Recruiter" above).

Quick and Simple: Enable SharePoint Designer workflow to update an InfoPath form

Scenario: I have an InfoPath form that front-ends a workflow process implemented using SharePoint Designer.  At one point, a manager must approve the form.  Since I cannot count on workflow history to meet my auditing requirements, I decide to store my own auditing message directly on the form itself.

Overview:

Design the form and publish it as a content type and the form itself to a document library.  Mark desired form fields as being updateable from MOSS.  The form is tied to the content type and the content type is "attached" to a forms library (or many, if you want).  Write a workflow that updates the field.

Specific Steps:

  1. Create a document library.  This will hold your InfoPath template.
  2. Create a forms library. 
  3. Create the InfoPath form.  Include a text field, "Audit Message". 
  4. Publish the form as a content type (NOT a document).
  5. While filling out the publishing dialogs:
    a) Save the .xsn file to the document library (step #1).
    b) Publish the "Audit Message" field and mark true: "Allow users to edit data in this field by using a datasheet or properties page".
    c) Create a new content type and give it an appropriate name.
  6. Access the forms library.
    a) Go to its advanced settings and enable the forms library to manage content types.
    b) Select the newly created content type (5c above).  It will be grouped under "Microsoft InfoPath" (or similar).
    c) Remove the default "Form" content type from the library.
    d) Mark the library to "show as web page" so that the form will launch from SharePoint and not the InfoPath workstation client.
  7. Go back to the forms library proper and click "New" to simply verify that the form is posted correctly and acting as you want.
  8. Fire up SharePoint Designer and navigate to the site that hosts your form library (from step 2).
  9. Create a new workflow attached to the forms library.
  10. Add a single action "Set Field in Current Item".  You should expect SharePoint Designer to list your your field, "Audit Message".  Assign it a value.
  11. Click Finish and go back to the form library.
  12. Create a new form and put some test value into the "Audit Message" field.
  13. Save it and go back to the form library.
  14. Right-click, select "Workflow" and start up your workflow.
  15. It should run almost immediately.  Pull up the form (from step 12) and if all has gone to plan, "Audit Message" has been assigned whatever value you provided in step 10.

Notes:

Not all controls may configured for this bi-directional communication.  For example, it does not seem to implement an SPD workflow that modifies text fields wrapped inside repeating sections. 

One of the key take-away’s here is that we’ve really created a content type with an associated template.  This also enables us to store multiple InfoPath form templates in the same form library.

This requires forms server.  It’s most certainly not going to work in a WSS 3.0 environment and probably even requires an Enterprise SharePoint environment.

The Beagle has Landed (October 2007 issue)

(This is actually a little old news, but as my favorite fire station motto proclaims, "Better late than never").

Check it out here: http://www.sharepointbeagle.com/

If you have not already, be sure to sign up.

Of course, be sure to read my article about a real-world SharePoint project (including requirements definition, KPI’s, content types, dashboards and more) as well as my colleague’s article about the content query web part. 

There’s lot of other good stuff too.

How to remove “View all site content” link

I’m asked this question nearly every week, normally in the context of a security discussion.  An administrator/site creator has provisioned a site, configured security, arranged web parts and customized the quick launch to provide that oh-so-perfect set of options to the end user.  But, out of the box, you can’t remove the "view all site content" link.

Mark Wagner provides the answer here (http://www.crsw.com/mark/Lists/Posts/Post.aspx?ID=36). His write-up is terrific on two levels. It provides an answer to the question, "How do I remove the View All Site Content" link?  Then, it answers the immediate follow-on question: How do I easily enable the view all site content link on a site-by-site basis?

As a bonus: His approach works for WSS, not just MOSS.

</end>

 Subscribe to my blog!

My very own CodePlex project: Workflow extensions for SharePoint Designer

UPDATE: See here (http://paulgalvin.spaces.live.com/blog/cns!1CC1EDB3DAA9B8AA!310.entry) for the latest on this project.

I created a CodePlex project today to house the Generic SPD interface code that I blogged about here (http://paulgalvin.spaces.live.com/blog/cns!1CC1EDB3DAA9B8AA!275.entry).

Have a look at here (http://www.codeplex.com/spdwfextensions) to see the CodePlex project and kick the tires.

If you’re interested in working on this with me, fire off an email at mailto:galvin.paul@gmail.com

SharePoint Designer — Custom activity to execute user-defined C# functions

 

UPDATE: This has been released to CodePlex here: http://www.codeplex.com/spdwfextensions

UPDATE: See here for latest release notes: http://paulgalvin.spaces.live.com/blog/cns!1CC1EDB3DAA9B8AA!381.entry

UPDATE: See here for my thoughts on commercializing this project: http://paulgalvin.spaces.live.com/blog/cns!1CC1EDB3DAA9B8AA!569.entry

This project provides a custom activity in SharePoint Designer.  Use this custom activity to invoke (dispatch) any C# function that you incorporated into the linked assembly.

As of late October, 2007, this is just an initial version of the project.  I plan to expand it with a number of additional functions, including substring, index, replace, invoking web services and anything that seems useful or interesting.  I also plan to post this to codeplex once I have my act together on that front.  This will also be deployable as a solution at some point.

If you have any comments, questions or suggestions, please leave them in comments or email me.

Disclaimer:

I make absolutely no claims as to the suitability of this for any purpose.  Use at your own risk.

Installation steps (to be followed for each WFE in the farm):

1. Download the .zip and extract.

2. Install the .dll into the GAC.  I usually open c:\windows\assembly using windows explorer and copy it there.

3. Modify web.config to add the assembly to the safe controls:

<System.Workflow.ComponentModel.WorkflowCompiler>
  <authorizedTypes>

<authorizedType Assembly="SpdGenericInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abe076fd8125f3c4" Namespace="Nivlag" TypeName="*" Authorized="True" />

4. Copy "SpdGenericInterface.actions" to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow

Note that the above location is specific to english language installations.

5. Close SharePoint Designer (if it’s already open).

6. iisreset

7. Open SPD and create a new workflow.

If all goes well, you should be rewarded with a new category of action:

image

 

Notes:

See here (http://blogs.msdn.com/sharepointdesigner/archive/2007/03/15/adding-activities-to-spd.aspx) for a terrific overview of the process for creating, installing and configuring a solution like this.

The .zip is designed to extract directly to you c:\ drive.  If you do this, you can open the project and all the paths will be consistent.

To use this in visual studio, you probably need to install "Extensions for Windows WF".

The initial upload contains just one "dispatcher function", "ToLower()".  To add more functionality, add it to the Execute method as shown:

 protected override ActivityExecutionStatus
          Execute(ActivityExecutionContext executionContext)
        {

            string functionToDispatch;
            functionToDispatch = this.DispatchFunction.ToLower();

            switch (functionToDispatch)
            {
                case "tolower()":
                    {
                        this.OutResult1 = this.InParam1.ToLower();
                        break;
                    }

                default:
                    {
                        this.OutResult1 = "Unknown function: [" + this.DispatchFunction + "].";
                        break;
                    }
            }

            return ActivityExecutionStatus.Closed;
        } // ActivityExecutionStatus

    }

Then, re-build the project and copy the assembly to the GAC.  I expect an iisreset would be required.

SPD Workflow custom action – get the <WorkflowInfo> tag right to avoid frustration

Part of the process for creating a custom action for SharePoint Designer involves create a ".actions" file.

I’ve found and tried to use a sample template which starts off as:

<?xml version="1.0" encoding="utf-8" ?>
  <
WorkflowInfo xmlns="http://schemas.microsoft.com/sharepoint/">
  <
Actions Sequential="then" Parallel="and">

However, that xmlns attribute prevents my environment from working.  My actions don’t show up in SPD. 

The solution is to strip out the xmlns attribute, do an iisreset and close/re-open SPD. 

Quick and Simple: Configure MOSS to search a specific document library

See UPDATE (I) below (11/24/07) on How to Configure Microsoft Office SharePoint Server 2007 to Index and Crawl Network Folders for Search

Objective: I want to execute a search restricted to a specific document library.  In this case, the document library contains training documents.

Steps:

1. Record the URL of the document library.

2. Create a scope:

Go to central administration.

Access the SSP.

Go to "Search Settings".

Scroll down to the scope section and select "View Scopes".

Create a new scope.  Give it a name and useful description.

3. Define scope crawl rules:

Add a rule that defines the document library for this scope.

Select "web address" for "Scope Rule Type".

Enter the name of your folder (see #1 above).

Accept the default value of "Include".

Wait for the scope to update (or start it manually).

4. Enable the scope in a site collection.

Go to site collection where you want to use this scope.

Add your new scope to the appropriate display group or groups.

5. Search!

At this point, you’re done.  Assuming the scope is properly defined, it will be available in the scopes drop downs for simple and advanced searches and when you search using that scope, you’ll just get results you expect.

Notes:

I wrote this blog entry because my searches for simple scope setup turned up dry using phrases like:

  • configure scopes in MOSS
  • configure search scope moss
  • scopes in sharepoint 2007
  • scopes in sharepoint
  • search a document library moss
  • scopes primer moss

You can create a search scope on a folder, not just the entire document library. 

A scope can be shared across multiple site collections (hence, a "shared service").

You can create the scope at the site collection level itself.  However, I prefer to go to central admin because I can start the crawl from there.  You cannot start the crawl from the site collection.

UPDATE (I) as of 11/24/07:

Kai Shang put together a great post entitled How to Configure Microsoft Office SharePoint Server 2007 to Index and Crawl Network Folders for Search @ http://kaishenghoo.spaces.live.com/blog/cns!8A7458DB12CA5AC9!206.entry