Jun28

Community Kit For SharePoint

Categories:

Just a quick note here…the Community Kit for SharePoint is ramping up again – new projects, continuing old projects, new approach and new goals. Stay tuned for more info on the projects we're looking to introduce and the approach and standards we will be supporting. I've been quite busy with this and a few other pet projects (plus that pesky day job…) lately but will soon have more info to post…

 

Dave

 
Apr30

Putting Social Computing to Work

Categories:

Newsgator is coming to town!

After this first event, stick around for a more technical discussion of NewsGator Social Sites at the May Philly Office Geeks meeting:

NewsGator Social Networking

5:00 - 5:30 - Food and Networking
5:30 - 6:30 - Ashley Roach from NewsGator
6:30 - 7:00 - Q&A. User Group Business
7:00 - Giveaways and wrap up

Keynote:
NewsGator Social Networking
Mirroring the consumer trend, social computing in the enterprise continues to gain momentum as more companies realize that the new capabilities deliver real business benefits. As the adoption of Web 2.0 in the enterprise continues to increase, so does the interest in using SharePoint as a social computing platform. NewsGator's presentation will offer attendees a better understanding of how to provide enhanced social computing capabilities within SharePoint. Presentation topics will include a) an understanding of the business benefits of social computing, b) a demonstration of Social Sites' features, c) a technical overview of the integration of Social Sites & SharePoint, and d) case study examples of how customers are using social computing to drive real business value.

Register for the first event here: http://www.newsgator.com/webinars/2009/mayseminar.aspx?LeadSource=HouseEmail%20&mtcCampaign=-1

Register for the second event (Philly Office Geeks) here: http://www.clicktoattend.com/?id=138000

Hope to see you at both events!

 
Apr29

Presentation for the Jordan SPUG

Categories:

I just finished my Enterprise Workflow session for the Jordan SharePoint User Group. Thanks for the opportunity, Mo! Unfortunately, we were plagued with audio problems because Vista kept switching from my headset to the microphone built into my laptop, but hopefully things were audible enough.

The slide deck from the presentation is available here: http://www.mannsoftware.com/PublicFiles/EnterpriseWorkflow.xps

I'll get the source code posted in a bit…

 

Dave

 
Apr27

TechDays Virtual Conference

Categories:

Thanks to everyone who attended my presentation at the TechDays Virtual Conference back on April 1st. I've just been informed that my session was the second highest ranked for overall satisfaction! Thanks to everyone, and I'm glad you enjoyed the session and found it informative.

 

Dave

 
Apr23

Philly .Net Code Camp

Categories:

Thanks to everyone who attended my session at Code Camp last weekend. Code Camp itself was a huge success – we had over 500 people and nearly 60 sessions. That's bigger than some conferences I've been to and this is all pulled off by volunteers. Kudos to everyone involved in putting this together.

 

In the SharePoint track, we had 5 great sessions, so thanks to John Angelini, Tony Testa, Michael Mukalian, and Joe McPeak for presenting. I was not able to stay the whole day, but it seemed that most of the SharePoint sessions had about 30-40 people in them. I counted 50+ jammed into the room for my session, so I think we may need to grow into a bigger room next time!

 

Thanks again and see you at Code Camp #2 in the Fall.

 

Dave

 

PS: Slides from my session are available here: http://www.mannsoftware.com/PublicFiles/EnterpriseWorkflow.xps

 
Apr22

Enterprise Workflow Presentation Material

Categories:

For anyone who attended my TechDays session or the Philly .Net Code Camp, the material from my presentation is available here: http://www.mannsoftware.com/workflow/Wiki%20Pages/Resources.aspx. I hope you found the sessions informative!

 

Dave

 
Apr5

SharePoint Workflow: Fault Handling

Categories:

 We'll handle this one with an excerpt from the book:

The functionality provided by fault handling in our workflows is no different from what you expect in typical .NET applications: you try something and then catch any errors and handle them. The implementation, however, is turned 90 degrees from what you would expect. Starting from the top, fault, or error, handling in our workflows is going to have the same capabilities as any other .NET application:

  • Faults can be caught within a local scope, or globally for the entire workflow.
  • Unhandled exceptions will cause the workflow to immediately halt execution and shut down.
  • Handled exceptions can be processed and allow your workflow to either continue processing or shut down gracefully, with as much logging or notifications as you need.

We'll cover the details on these as we go through the rest of this section. First, let's review some of the mechanics of how you configure fault handling in workflows. The primary construct for handling errors is the FaultHandler activity. We'll walk through using this activity in just a bit, but at a high level, each FaultHandler activity is associated with one particular type of exception and contains other activities that dictate how the particular error is handled.Like any other error handling, the goal of fault handling in WF is to trap errors as they occur, respond according to our business rules, and ideally allow the workflow to continue processing. If continuation is not possible, we need to clean things up and return our documents or other content to a stable, manageable state.At a global level, exception handling can be applied to the entire workflow. To do this you are going to make use of the three little tabs (shown in Figure 9-4) at the bottom of the Workflow Designer pane in Visual Studio that we haven't paid much attention to as yet. Specifically, we're going to focus on the rightmost tab.

Figure 9-4. The tabs at the bottom of the Workflow Designer in Visual Studio provide access to the fault handling functionality.

Clicking on that tab will reveal the Workflow Exceptions design canvas, shown in Figure 9-5. Even the most cursory glance will reveal that the Exceptions design canvas looks nearly identical to the Workflow Designer we've worked with so far. That is not an accident. Configuring our exception handling is just configuring another part of the workflow. Looking at Figure 9-5 a little more closely, you'll see it consists of a single composite activity of type faultHandlersActivity. This composite, like all of the others we've seen so far (Sequence, Parallel, While, IfElse, etc.) is made to serve as a container for other activities. This one is a little special, though, because it is made to store only one type of activity: the FaultHandler activity mentioned earlier.  If you try to add any other type of activity to it, the Designer will not let you.   If you try to add any other type of activity to it, the Designer will not let you.

Figure 9-5. The Workflow Exceptions design canvas looks remarkably like the regular Workflow Designer canvas we've already worked with.

One other thing that is different about this composite activity is the manner in which it displays its children. Because each of the children is another composite activity, the tree display could get very ugly, very fast. To help alleviate this, Microsoft has coded the faultHandlersActivity to display its children in a unique way - essentially each FaultHandler gets its own design canvas. Each FaultHandler child dropped onto the faultHandlersActivity parent will be displayed in the small ribbon-like construct at the top of the activity. The two blue arrow icons allow you to scroll back and forth between the FaultHandler activities that have been added. The main body of the activity below this will display the child activities from the currently selected FaultHandler.That's a little confusing. Let's walk through an example to help clarify things:

  1. Open or create any workflow.
  2. From the designer canvas, click the right-hand tab located at the bottom of the screen. This will open the Workflow Exceptions design canvas.
  3. From the Toolbox, drag two FaultHandler activities and drop them onto the faultHandlersActivity on the canvas
  4. Click on the first FaultHandler activity—indicated by this icon on the left side: 
  5. Drag a Code activity and drop it into the body of the faultHandlerActivity1 activity - where the small green plus sign has appeared.
  6. Click on the second FaultHandler activity - indicated by same icon shown in step 4, this time on the right side. Notice that the Code activity has disappeared. This is because we are now working with a different FaultHandler activity.
  7. Drag an IfElse activity from the ToolBox and drop it into the body of the faultHandlerActivity2 - again where the small green plus sign has appeared. Add another Code activity to the left-hand branch.
  8. Click back on the first FaultHandler - you'll see that the Code activity is still in place.

If you click back and forth between the two FaultHandler activities, you'll see that everything is still intact - you just have two totally distinct environments in which to handle errors. This, of course, begs the question of why you need separate environments. The answer is that you need multiple environments in order to explicitly handle different types of errors. It is the equivalent of the code shown in Listing 9-1.

Listing 9-1. The Code Equivalent for Our Workflow Fault Handling Constructs

try

{

//do something

}

catch (System.NullReferenceException exNull)

{

//handle a null reference exception

}

catch (System.ArithmeticException exArith)

{

//handle an arithmetic exception

}

catch (System.Exception ex)

{

//catch-all to handle any other error

}

 Each FaultHandler activity represents one of the catch blocks in Listing 9-1.

Configuring Fault Handlers

There are two ways to configure fault handling for our workflows - declarative or imperative. The imperative type of fault handling requires setting one set of properties, creating variables, and writing some code to handle the error however we need to. We'll show this option in a minute. Declarative handling is slightly different. When we handle our workflows declaratively, we work exclusively in the Designer - adding activities to the canvas and setting properties to handle our exception. We don't write any code. We'll cover this next.

Declarative Fault Handling

Declarative fault handling is all about adding activities to the canvas and configuring them to handle the exception according to your business rules. One of the primary distinctions of this approach is that it is somewhat generic in nature; the only real information you know about the fault is its type—and that only because, as we saw earlier, each FaultHandler is configured to handle a particular type of error.So, how do we work with this style of fault handling? As you would expect, it's really pretty straightforward if you're comfortable with the Workflow Designer.

  1. From the Exceptions tab in the Workflow Designer, drag a FaultHandler activity out onto the canvas.
  2. Make sure that the FaultHandler activity is selected and open the Properties window.
  3. Inside the Properties window click on the ellipsis for the Fault Type property. This will bring up a dialog box, shown in Figure 9-6. This dialog box allows you to specify which type of error this particular FaultHandler activity will take care of.
  4. Once you've specified the type of error to be handled by this FaultHandler activity, you can add whatever activities you need to in order to handle the error.
  5. If you need to handle more than one exception type, drag another FaultHandler activity out and configure it in the same way.

OK, I have to jump in here and editorialize a bit. I don't understand the usefulness of declarative fault handling (except for one circumstance, which I'll get to in just a minute). Here's the problem I see - if I'm catching and handling an error, I want to be pretty specific about the way I handle it. Also, in most cases, the error being thrown is likely unique to the workflow that is running. Because of these two points, I need my handler to be specific, which means that I'm likely adding a Code activity and writing some code. Once I've crossed that line, I'm into the realm of imperative fault handling. The only exception I see to this is if all you are doing is simple logging. In that case, write a custom, generic logging activity that will write the information to whatever logging medium you require, add it to the Designer for your fault handler, and you're good to go. No coding required, but you still get some useful information and didn't have to write any code specific to this handler.  Other than this one case, I recommend that you read on and understand the benefits of imperative fault handling—it's a little more work but well worth it for the extra value, as you'll see.

Figure 9-6. This dialog box indicates which type of exception is handled by our FaultHandler activity.

Imperative Fault Handling

Imperative fault handling, as I alluded to earlier, is a little more involved than simple declarative handling. However, it gives us a lot more control and a lot more capability to manipulate our handler process and to be specific with how we process our faults. Imperative fault handling makes use of one new property of the FaultHandler activity: the Fault property. The Fault property allows us to create a property that will be used to store the object representing the exception that was thrown by our workflow. With that, we can then handle our exception however we need to, typically within a Code activity. When the exception is thrown, we will have access to the entire Exception object through the variable referenced in the Fault property.To make this work, follow these steps:

  1. Repeat steps 1 - 3 from the previous section.
  2. Right-click on the FaultHandler activity and select Promote Bindable Properties from the context menu.
  3. Take a look in your code-behind file and you'll see that a new dependency property, named <Fault_Handler_Activity_Name>_Fault1, has been created for you. For example, if your fault handler is named faultArgExcep, then the dependency property will be called faultArgExcep_Fault1. The new property will have a type of System.Exception. If you choose to, you could make the type for this variable more specific.
  4. You'll still need to fill in the FaultType property to tell the workflow runtime which type of error this particular handler is taking care of. For this example, you can type in System.Exception.

That's it. If your workflow ever triggers this handler, your dependency property will store reference to the exception that was thrown. You can drop a Code activity onto the canvas, reference the dependency property, and do with it whatever you need to do in order to handle his error. The main benefit is that you have a lot more information about the error available to you. To harp on logging again—placing some of this information (stack trace, source, etc.) into our logging is going to make errors much easier to troubleshoot.

Local Scope

So far, we've looked at fault handling at what is essentially the global level. We've created handlers for faults that bubble up, unhandled, to the top of the chain - the workflow itself. One definite problem with this is that when you are capturing errors at the workflow level, there is no way to continue the workflow after the error has been handled. Faults caught at the workflow level always immediately precede the termination of the workflow. This is obviously less than desirable. So, what can we do about it? Fortunately, there is an option. Faults can also be handled at the level of any composite activity, so the Parallel, Repeater, Sequence, and While activities (just to name a few) can all handle faults at a more granular level.Handling the errors at the level of a composite activity is exactly the same experience as we saw at the global level. The only thing that is different is how you access the fault handler design canvas for a specific composite activity—simply right-click on the activity itself and select View Fault Handlers from the context menu. That's it. The rest is identical to what I described earlier.

TipWith the scope issues discussed in this section in mind, I recommend that you make judicious use of some of the composite activities that ship with WF. Certainly the Parallel, IfElse, and While activities have their place by performing a specific function in addition to being composite activities. There is, however, the Sequence activity, which can be used when you are executing activities serially but still need to be able to handle faults locally.

If an error is not explicitly handled at a local scope, it will bubble up to the global handler to attempt to be handled there. If the global handler does not take care of the error, the workflow will error out with unpredictable results - including potentially leaving your documents or tasks in unknown states.

Fault Handling Summary

So now we have a pretty good idea of how we go about handling faults in our workflows. The only thing that I'd like to conclude this section with is a brief discussion of how you should handle errors in your SharePoint workflows:

  • As I alluded to previously, you should always log the error. Whether this is with code or a logging activity is entirely up to you. I'll just leave the recommendation at this: log it somewhere.
  • Local, local, local. Whenever possible, handle your faults as locally as possible.
  • Always, always provide a catchall fault handler at the workflow level. Add a FaultHandler activity at the workflow level and configure it to catch exceptions of type System.Exception. If it does nothing else, log the error details somewhere.
  • If tasks were already assigned, you should go back and either delete them or flag them as inactive. Specific details around this would be dependent on your particular business requirements, but it wouldn't do much good, and could potentially be very confusing, if participants had tasks assigned to them for a workflow that had errored out.

CautionIf you are going to undo changes in your workflow because of an error, you should understand how workflows process operations in batches and do some experimentation with your particular situation. Go back and read the section "Workflow Processing" earlier in this chapter before proceeding too far down this road. Specifically when your workflow will commit operations to the database is unique to every workflow. Keep this in mind as you plan your fault handling.

 

 
Apr3

Workflow Resource Center

Categories:

Unfortunately when my old hosting company "forgot" how to run a web server, I lost a fair amount of stuff. I had set up a Workflow Resource Center on my old blog and now find that I need to do so again: http://www.mannsoftware.com/workflow. I'll be building it out and adding content over the next few days to get things back to where I had gotten them before, and then maintaining it over time.

Dave

 
Mar23

The Missing “Change Item Order” menu

Categories:

[Update]

Right after posting this, I realized that the menu item only shows up for the "All Links" view. So, even if you have another view in the List, just navigate to the All Links view and the menu item will be available.

[/Update]

One of the benefits of the Links list type is that it comes with the ability to reorder the items in the list via a nice UI, as seen here:

takes you to this page:

 

There's one catch, though. As soon as you add another View to the list, the menu item disappears:

 

The functionality is still available; it's just the menu item that disappears. If you manually navigate to /_layouts/Reorder.aspx?List=[List GUID], then everything works fine. If you delete the extra view, then the menu item comes back.

I [Update] STILL [/UPDATE] wonder why this works this way.

-Dave

 
Feb11

Changing the master Page for a site with publishing (layout) pages

Categories:

I knew this at one time, but my Swiss cheese brain apparently forgot it at some point…

Simply changing <SPWeb>.MasterURL works perfect for WSS and Application pages, etc. However, it's only half of the answer when you toss publishing and layout pages into the mix. In that case, you also need to set <SPWeb>.CustomMasterURL:

site.MasterUrl = myNewMasterURL;

site.CustomMasterUrl = myNewMasterURL;

site.Update();

Dave

 
 Next >>