Skip to content

Slide Decks from SharePoint Pro 2010 Summit

Last week I had the pleasure of delivering a pre-conference session and three regular sessions at SharePoint Pro in Las Vegas. Several folks have asked to get copies of the slide decks, so I’ve uploaded them with links below:

I should say that there were plenty of demos, which obviously aren’t in the decks. However, the decks should be a useful reminder if you were there.

Creating Intelligent Content Types with Word, SharePoint Designer, and Visual Studio

In Office and SharePoint 2007 we had the capability of creating a content type that was intelligent – one that allowed you to specify fields in your document and have those promoted to the SharePoint library the content type is in. In fact, I wrote about this in my “Managing Enterprise Metadata with Content Types” whitepaper that I wrote for Microsoft. However, in that whitepaper I only talked about how to do the creation of the content type from the user interface – you couldn’t pick this content type up and move it from one site collection to another. Of course in SharePoint 2010 you can use the Managed Metadata Service but that requires server – and a connection between farms. What if you want to pickup a content type and move it from one farm to another that aren’t connected – or if you don’t have server.

The good news is that the tools in Visual Studio 2010 are much better than in Visual Studio 2008. I put together a video as a part of my work for SharePointPro Summit. The video shows how to create a new hire form and then turn that into a package that can be redeployed.

Take a look at how easy it is with the new tools to Create a Content type and package it.

Infrastructure Ripple Effect – The Story of Servers, Racks, and Power

A few months ago I decided that I needed a new server. (It was actually several months ago but a few months ago I gave in and decided to buy it.) My server infrastructure was outdated. I did pickup a new server to put at the collocation center a year and a half ago. However, that server isn’t local to me and I still need something that is local for file storage, DNS, DHCP, etc.

I also needed to have a Hyper V host machine for some work I’m doing with Microsoft on the 10232A “Designing Applications and Solutions for Microsoft SharePoint 2010” class. (i.e. Professional SharePoint Development course). My Lenovo T61p laptop doesn’t work as a HyperV host – or at least hasn’t worked until recently. Ultimately the fact that HyperV disables Suspend and Hybernate means it’s not a good fit for the laptop.

So I decided to buy a Dell R710 rackmount server. I added some processors, memory, disks, etc. so that it can be a complete virtualization platform here in my office. I did get the remote access card so I could check on the server while I’m not here. Anyway, that seemed like it was all good, I mean I had other servers in my rack already … that was until it arrived.

I had conveniently forgotten that I had a telecommunications rack which is only 24 inches deep and servers (at least the professional servers) expect a 30″ deep rack. Setting the server into my old rack was semi-comical as it was sticking out both the front and back of the rack. So… I picked up a new rack. An IBM NetBay 25U rack that works pretty well in the space I have. The rack is way oversized for the 2U of server and the 1U of switch gear. However, 25U was the right size at the right price.

When I ordered the server I picked up dual power supplies to minimize points of failure. Of course, if you have two power supplies you might as well have two different electrical circuits – so I paid the handyman to install a second 20 amp circuit into my server/storage room. (I even had him put it on the opposite leg of the power just in case we had a single leg power failure.) That lead to a desire to have two UPSs… and they might as well be rackmount since I’ve got all of the extra space in the rack. I’ve had good experience with APC UPSs both personally and professionally so I settled on the SUA2200RM2U – 2200VA or a full 20Amp capacity.

This lead me to try to install the APC PowerChute software on the Dell which by now was running HyperV and several virtual machines. What I discovered is that the Power Chute software didn’t support Hyper-V. A bit of research lead me to seeing Ben’s post about support or UPSs in Windows. That’s fine but I really wanted automated testing and better support than is available out of Windows.

Of course, the PowerChute Network Shutdown supports Hyper V. So I buy the network cards for the UPSs and install them. After some real fun trying to get them configured because you have to use the APC serial cable – and you have to disconnect the USB connection before the serial port will work. I finally get them configured and discover that despite what an APC agent told me the PowerChute Network Shutdown software (free) doesn’t support HyperV. Instead, there’s a specific HyperV version that does support Windows HyperV hosts – but of course it costs another $99. (At this point I’m not too concerned about the cost but it is frustrating that it isn’t included with the network cards and that an agent had told me it wasn’t necessary.)

I still don’t have it all configured exactly as I want it. However, at least the fundamentals are in place. I’ve probably got one more purchase to make. My Linksys switch SGE2000 can have a secondary power supply (an RPS1000) attached to it. The RPS1000 would allow me to have one power supply plugged into the first UPS and the second one into the secondary power supply. Thus the switch would keep running even if the first UPS had a problem. I wouldn’t do this except that now that I have the UPSs on network cards the switch becomes a point of failure in a power outage situation.

I am reminded that any change creates a ton of little ripples.

The Public Debut of Super Pig

At the SharePoint Conference 2009 they were handing out flying pigs – including their capes. So my son and I developed a short story board, recruited a neighborhood friend and put together a little short movie staring Super Pig (the flying pig given away at the SharePoint Conference.) Take a look for yourself: https://thorprojects.com/wp-content/uploads/2015/07/SuperPig.wmv

I’ve had this put together for a while – since everyone I’ve shown it to likes it so much I had to share it with the world.

Sending HTML Emails with System.Net.Mail.MailMessage is more than IsBodyHtml

It seems like lately I’ve been running into a series of things that should be easier than they’re turning out to be. I’m not sure exactly why that is – but I’ve got another fun one to share.

So System.Net.Mail.MailMessage is the object (along with SmtpClient) which are used to send emails. There’s a single property on MailMessage called IsBodyHtml that is supposed to indicate that the body of the HTML should be treated as Html. That’s all fine and good except that my experience is that it doesn’t work consistently. In fact, it rarely works for me. So how do you make it work? Well, you add Alternate views. MailMessage has a property AlternateViews which is a set of alternate views that can be displayed with the message. In order to get a HTML view I had to add a new AlternateView with the encoding of text/html or System.Net.Mime.MediaTypes.Text.Html. So when I want HTML I add this code to the bottom of the place where I’m sending the message:

AlternateView av = AlternateView.CreateAlternateViewFromString(msg.Body, new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Html));

av.TransferEncoding = System.Net.Mime.TransferEncoding.SevenBit;

msg.AlternateViews.Add(av);

I also generally add one for plain text encoding for those email readers that can’t cope with HTML which can be done by replacing the content type with ‘Text/Plain’ like this:

AlternateView av = AlternateView.CreateAlternateViewFromString(msg.Body, new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain));

av.TransferEncoding = System.Net.Mime.TransferEncoding.SevenBit;

msg.AlternateViews.Add(av);

Hopefully this will make it easier to figure out what is wrong when you are trying to send HTML email messages and it isn’t working.

OnWorkflowItemChanged and Workflow Event Delivery problems

One of the problems that I recently ran across was that I had a workflow that would stop getting events delivered to it while it was running. It wasn’t clear what was going on but with some help from Eilene Hao Klaka and Gabe Hall we were able to sort out the root issue. So let’s take a rather simple workflow:

The key here is that the workflow watches the item using OnWorkflowItemChanged then stops watching the item while it works on watching some tasks and then it resumes looking at the workflow. This looks pretty harmless and it is – right up to the point where someone makes a change to the document when the workflow is looking for task updates – but not item updates. When this happen the workflow gets the event, can’t process it – and ultimately it’s no longer runnable. It won’t respond to any more events or take any more actions. Making matters worse is that you don’t so much as get a message in the ULS that this has happened.

So what’s going on? The short of it is that the workflow host and workflow foundation believe that you need events on the item in the middle of this workflow because the scope of the correlation token for OnWorkflowItemChanged is the workflow itself. So even though there’s not an activity that is listening – the WF host and foundation believe there should be. The first thought might be to change the scope of the correlation token for OnWorkflowItemChanged to something smaller – but that won’t work because OnWorkflowItemChanged expects the token created at the scope of the workflow.

However, there is another approach that will work. You can setup a subscription for your own event by using the CallExternalMethodActivity, selecting the InterfaceType of Microsoft.SharePoint.Workflow.IListItemService and selecting the method name of InitializeForEvent. You’ll also need to provide an ID ([Updated]The guid from the workflowItem workflowProperties.Item.Guid), the itemId (which in our case we can get from workflowProperties.ItemId), and listId (again we can get this from workflowProperties.ListId). This sets up a subscription for events. The second activity we need is HandleExternalEventActivity. In this activity we select the same InterfaceType of Microsoft.SharePoint.Workflow.IListItemService and select an EventName of OnItemChanged. This will get signaled when the workflowItem is changed. The beauty of this is that you can place these two activities inside of a sequence activity and set the correlation token to the scope of the sequenceactivity. When the correlation token falls out of scope, the subscription for the events will automatically be removed.

I’ve bundled this into a custom sequence activity. The sequence activity that I’ve prepared will allow you to bind the SPWorkflowActivationProperties (workflowProperties) from which the activity will automatically get the listId and ItemId – or you can bind them individually. I’ve also allowed you to bind to the subscription id – while I don’t know why you would need this, I was trying to be complete. Finally, I also added a Invoked method so you can run code based on the event happening. CAUTION: I’m not setting the sender when I call your method so you’ll not want to use this for anything that requires the sender object. (i.e. for those cases when you need to know what branch you’re in.) This is the same problem that OnWorkflowItemChanged/OnTaskItemChanged has – so I didn’t see this as a big issue. The activity looks like this:

The code is available here – use it at your own risk.  All you need to do is replace your OnWorkflowItemChanged with this activity and the rest of your workflow should remain undisturbed.

[Update 2010-07-27] There are a few issues with the initial post.  I originally called out that the subscription ID be a random Guid — this isn’t correct, the Guid needs to be the guid of the document that the workflow is running against.  Second, You need to make sure that you want the event that you’re subscribing for.  If you quickly subscribe for an event and then exit the scope you’ll have problems.  Finally, I adapted this approach to put the listen in the middle of a while loop to ensure that I wasn’t subscribing and falling out of scope repeatedly.  Unfortunately, this adaptation can’t be packaged as an activity because of a bug in Visual Studio 2008 (the problem doesn’t exist in Visual Studio 2010).  The bug prevents you from providing the condition to the while activity in your custom activity.  The workaround is to simply replicate the pattern directly in the main workflow.  Although this is tedious it works. — rlb

OnTaskCreated, DelayActivity, and PersistOnClose – How you can force the creation of a task

I’ve been working on a rather complex SharePoint workflow and I’ve run into a few problems. The workflow does a parallel approval of a form – and well, I’ve discovered a few issues.

First, there aren’t many examples of how to do parallel approvals. This is particularly true when you need to keep unique instance data per iteration of the replicator loop. However, by scoping the correlation token to the inner sequence activity in the replicator, using a custom sequence activity to hold the additional parameters you need, and using the ChildInitialized event of the replicator that can be done.

However, I also ran into some odd problems that only occur when a workflow is doing parallel execution. But before I get there, I have to explain how CreateTask works. The CreateTask activity doesn’t actually create a task immediately, it creates a request to create the task when the workflow is serialized. The basic thing is that they want to minimize disk IO on the SQL server so if you wanted to change things after creating it – but before it’s written to disk in the list – you could. However, there are many situations where you need to force the task to be created so you can start to use it in your loop conditions. Commonly you want to know if the item exists and isn’t completed. If you put this at the top of a while loop immediately after a CreateTask you’ll never enter the while loop because the task will be missing from the point of view of the condition.

To every problem there is a solution, enter the OnTaskCreated activity. But wait, I have to mention that Microsoft is recommending that you not use OnTaskCreated – if you don’t believe me check out KB 970548. They say to use DelayActivity. I’ve commened on DelayActivity in the past, particularly about the fact that you can’t have a DelayActivity that runs for less than a minute. Well, I was wrong. There’s a situation where you can have a DelayActivity fire in less than a minute.

If you’re running a parallel situation (say inside of a replicator) and you hit a DelayActivity the wait is put on a timer queue inside of the workflow – just like any other workflow foundation workflow. The other branches will continue to run while the DelayActivity quietly ticks off the time. So it is technically possible to have DelayActivity sit for less than a minute.

In my case, I had set my DelayActivity to one second and didn’t think anything about it. That is until I got a Null reference exception thrown back at me from the workflow. Why? Well, it seems like in the serialization process for the workflow the event fired and well, the SharePoint workflow host didn’t know what to do with it. (Reportedly this is fixed in SharePoint 2010 but I’ve not tested this.) So now what do I do?

Well, enter the PersistOnClose attribute. This is an attribute in the Workflow Foundation that signals to WF that the workflow should be serialized immediately after completing the activity. This sounds pretty good… I can do a create task then an activity that has this attribute and all is well. Of course, if I had 100s of parallel branches in a workflow this would be sort of abusive on the system forcing it to serialize a workflow 100s of times – but for my case where I’m only ever a dozen or so branches wide at the same time it works fine.

All I did was I created a new activity that does nothing – except it has a PersistOnClose attribute on it. I put this immediately behind my CreateTask and voila. I get my task created. There’s no crazy eventing going on. There’s no delay while the system goes to sleep and wakes back up – just a little extra overhead on the system.

Problem solved. It’s more than a bit crazy how you solve something like this – but it works and I’ve got one less problem to worry about.

[Update: You can download a copy of my code (use at your own risk) here.]

SharePoint Saturday Wrap Up and Thank You

Last Saturday, January 30th 2010, we did a SharePoint Saturday event here in Indianapolis. From the perspective of most folks it was a roaring success. Kevin Dostalek posted his recap already. David Petersen posted a few pictures before we got rolling. Woody Windischman, Chris Geier posted about their experiences and both Enrique Lima and Rob Wilson posted their slide decks.

For me I felt like I was in the center of the storm. Officially the SharePoint Users Group of Indiana executed the event. (i.e. the users group held the money) However, I can honestly say that my introduction to the steering committee was correct – I didn’t really feel like I did that much. In my conversations with the other members of the steering committee they felt largely the same way. That – to me – says a lot about the group of folks committed to making the event a success. We all compete for business in Indianapolis – and at the same time we worked together to deliver a community event that most people walked away from happy.

I wanted to say thank you again to the sponsors: Ambassador, Apparatus, CDW, Idera, K2, Microsoft, SHI, Wrox. Without their generous support the event simply wouldn’t have been possible.

I also wanted to thank everyone for coming. A SharePoint event in Indianapolis with 372 registrations and 250 attendees should demonstrate what a great community we have in Indianapolis.

Inside the Way Back Machine, Inside Access

This talk of Access Services got me to dig up my copy of Inside Access and take a few pictures:

You may notice my name in the upper right – and the date near the lower left. This is one of the first two books that I worked on. (I think it was second but I’m actually not sure.)

Some of you may not recognize what that second picture is of – it’s a picture of a 5.25″ floppy disk. That’s right it’s flexible. This one is available for read/write (see the notch on the upper right.) With 360K of storage and a 360 RPM speed this baby was all the rage – 17 years ago.

In case anyone’s wondering – the book is a museum piece now – I don’t refer to it daily.

Recent Posts

Public Speaking