Thursday, February 9, 2012

Improving Workflows with a Status Column

Of the many things that SharePoint does well, it rocks as a workflow host. The problem, though, is that SharePoint doesn’t do a great job of showing you where you are in your workflow. This isn’t really SharePoint’s fault; SharePoint doesn’t know what you’re attempting to do with your workflow. But the problem is that I want to make sure my users can easily see what the status of a workflow is.

Consider a simple trouble ticketing list. Users submit a trouble ticket which kicks off a workflow for a technician to handle the problem. If I’m the manager I want to be able to easily get an overview of how many items we have outstanding. By default, the only thing that SharePoint will display on the list is the overall basic status of the workflow: In Progress, Completed or that there was an error. This doesn’t really help me see the true status of the items. Granted, I could click on the link for the workflow and read the history, but that becomes tedious very quickly. Plus – I’d love to be able to take advantage of the cool grouping features that SharePoint lists offer me.

Without Status Column - No groups or filters

Fortunately, the solution is simple – add a column to show the status. In fact, for nearly every workflow I create I add a column to show the current status. This allows me to move beyond the three uninformative messages the workflow will give me by default, and allow interested parties to quickly filter and group based on the status of a workflow.

Grouped by Status

Filter by status

In the above example, I simply add on a choice column to show the current status (In Progress, Escalated, Resolved, Unresolved, etc.) and then ensure that the appropriate steps in the workflow I update the status. Now when I go to view the list I can see the blow, which is much more informative than the above.

So frequently it’s the little things that make our SharePoint users’ lives easier. Adding a column for the real status of a workflow is one of those little things, and something to consider on every workflow we create.

Wednesday, February 8, 2012

Allowing Users to Configure Web Parts

Every SharePoint developer class I teach has a module on web parts. Needless to say[1], this is one of the most popular modules because I do a couple of killer demos[2], and because creating web parts is a big part of most SharePoint projects.

However, simply creating a web part is not enough. The web part must be configurable by the user – I want to ensure the user has the ability to adjust the web part for their specific needs. Once you determine the personalizable properties of the web part, the next question is what interface you want to use to accept the information. After all, there are many ways that this could be accomplished, including a custom editor, a connected web part or your own custom UI that you place on the web part itself.

Of the three listed above, my least favorite is to create a custom UI on the web part itself. The first reason for this is you’re creating a UI for an environment that already has a UI for accepting personalizable values – the web part editor itself. Additionally, the user will[3] have been trained how to edit a web part. If I add a custom UI to the web part itself, I’m now providing exceptions to the normal rule for my users. I want my users to have a consistent experience. Nearly every other web part is configured through the editor, so I’m going to leave them there.

The next option is to create a custom editor. A custom editor allows me to inject my own UI into the normal SharePoint web part editor section. This allows me to add on validation and give the user a better experience, all while maintaining consistency at the same time. I’m a huge fan of this, and for the most part I don’t create a web part any longer that doesn’t have at least one custom editor. The SharePoint editor, and in turn the custom editors that I create, are perfect for personalizable values that will persist over time and rarely change. I call these “Set it and forget it” values – ones that will be set when the web part is added to the page and updated infrequently.

The last option for allowing the user to set a value that a web part will act upon or persist is to create connected web parts. A connected web part allows the user to place two web parts on a page, select or update a value on one and see the result on the other. Connected web parts are great for settings that need to change frequently, or providing the user the ability to interact with the data. That being said, you can achieve the same result, like a master/details view, in a single web part. In a single web part, you’re to easily take advantage of AJAX calls to avoid the round trip a connected web part will typically need. While AJAX is cool, it’s also nice to allow the user place the two connectable web parts anywhere on a page and let the user decide what form of a UI will work best for them.

As with everything in SharePoint, there is no one correct answer. The best approach is to analyze the situation, interview your users and figure out what is most appropriate for your situation. But I would say that as a basic guideline that a connected web part is best for the interactivity needed when looking for something along the lines of a master/details view, while most (if not all) other personalizable properties are best set through the SharePoint editor, preferably with your own custom interface.

[1] Why is it that people say “needless to say” but say it anyway?
[2] Although I might be biased.
[3] …hopefully…

Monday, December 26, 2011

Disable Office 365 Retention Policy

Recently I made the move from Google Apps to Office 365. I love cloud services for mail, especially ones that allow 25G+ of mail storage. However, I was a bit shocked to find out that the default retention policy is set to 30 days. I basically never want my email deleted as I never know when I’m going to need a message later. Fortunately, with just a little PowerShell, this is easily fixable.

The first step is to get connected Office 365 via PowerShell. As Mike Pfeiffer shows us, this is easily accomplished with the following three PowerShell Commands:

$cred = Get-Credential

$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic -AllowRedirection

$importResults = Import-PSSession $s

(The second command is all one line – formatting issues) :-)

Upon executing the first PowerShell command (Get-Credential) you’ll be prompted for a username and password. Use your Office 365 administrator’s credentials.

Then the command to disable the retention policy for the mailbox is as follows:

Set-Mailbox <name> -RetentionPolicy $null

Make sure the <name> is the email address for the mailbox you wish to disable the retention policy for. And fixed!

Thursday, December 15, 2011

Remove System Account from Workflow History

SystemAccountYesterday I blogged about keeping System Account out of the Modified By column. Today I want to tackle the other annoying place System Account rears its ugly head – workflow history.

The LogToHistoryListActivity determines who it will log as by reading the ID in the UserId property. By default this property is set to –1, meaning the System Account. What we need to do is set this to the ID for the user. How we go about finding the user ID and assigning it will vary a bit.

If we’re looking for the person who kicked off the workflow, this is pretty easy. After dragging out your LogToHistoryActivity, bind the UserId property to workflowProperties.OriginatorUser.ID.

If you’re looking for the user who modified a task, you’ll need to perform a couple of steps.

  1. Add a field or property to the workflow to store the ID for the user of type Int32. I like to simply call mine logUserId.
  2. Create a new binding on the OnTaskChanged activity for the Executor property. This will contain the string for the login name. I call mind taskExecutor.
  3. Create a little helper method in the code to update the logUserId. I like mine UpdateLogUserId():
    private void UpdateLogUserId()
    {
       logUserId =
          workflowProperties.Web.EnsureUser(taskExecutor).ID;
    }
  4. Ensure the UpdateLogUserId() method is called before the LogToHistoryListActivity executes – this is most easily accomplished by making the call in the Invoked event handler for the OnTaskChanged event handler.

For each OnTaskChanged event handler and LogToHistoryActivity you simply need to ensure steps 1, 2 and 4 (since the method will have already been created) and you’re all set!

Now we can hide System Account from our users once and for all.

Wednesday, December 14, 2011

Avoiding System Account in “Modified By”

When creating event receivers or workflows you frequently need to update the list item in question in that code. The problem with doing this is it typically requires changing the user context to someone who has permissions to perform the operation (frequently the System Account or another privileged user). You usually want these changes to occur behind the scenes and not be displayed to the user.

Consider the following little example for an event receiver:

public override void ItemAdded

                          (SPItemEventProperties properties)

{

   SPUser adminUser =

       properties.Web.EnsureUser("GEEKTRAINER\\charrison");

   using (SPSite site =

       new SPSite(properties.WebUrl, adminUser.UserToken))

   using (SPWeb web = site.OpenWeb()) {

     SPList list = web.Lists[properties.ListId];

     SPListItem item = list.GetItemById(properties.ListItemId);

 

     item.BreakRoleInheritance(true);

     item.Update();

   }

}

Pretty simple demo code for an event receiver. First I’m changing context[1] to a privileged account. Then I’m loading up new instances of the SPSite, SPWeb, SPList and SPListItem objects in order to make changes. I then perform the change and call Update() on the list item. The result? Well, the result looks like this for a user named Susan who creates a new announcement in this list:

BeforeCallingSystemUpdate

You’ll notice that it says the item was updated by Christopher, which is true – it was modified by Christopher, but that’s not the display I’m looking for. The item was created by Susan, and Susan should be the only person shown on the Modified By column.

Thus enter SystemUpdate[2]. SystemUpdate allows you to change a list item without changing either the Modified or Modified By fields. Behind the scenes, SystemUpdate will still update the audit log, however it will not send alerts for the changes.

SystemUpdate has two two overloads, SystemUpdate() and SystemUpdate(boolean). The second overload allows you to control if a new version is created by passing in true. The default (no parameters overload) is false – don’t create a new version.

If we update the line:

item.Update();

to be:

item.SystemUpdate();

and then create a brand new item again as Susan, you’ll notice the difference (the one titled “Modified by Current User”:

AfterCallingSystemUpdate

SystemUpdate allows you to make changes to list items in code and essentially “hide” those changes from the user. The audit logs will still record the change, but the user will not see the dreaded “System Account” (or other account) in the Modified By column.

[1] See blackninja for a demo on changing context.
[2] See MSDN for the full documentation.

Wednesday, November 30, 2011

Taking Your Developer Skills to the Next Level

IMG_0017There are many courses and books on the market that will teach you C#. When you finish one, the world of .NET is now open to you. However, merely knowing the syntax of the programming language isn’t the entire story. In order to be a good developer we need to learn conventions, best practices, and when to apply the techniques we’ve learned – and when not to! Fortunately, if you’re willing to invest the time, getting over that wall and taking your skills to the next level is within reach. While everyone is different, here’s a list of resources (books) that have helped me improve my skills as a developer.

Applying UML and Patterns (Craig Larman) – While not a .NET book, this book picks up where most C# courses and books leave off. You know the syntax but not the techniques of proper object design. The code samples are in Java, but if you know C# it’s a pretty straight forward translation. Besides, it’s the skills we’re interested in rather than the syntax itself. What I love about this book is how down to earth it is, and that Craig walks you through every step of his small case study, explaining every decision that he makes.

Refactoring: Improving the Design of Existing Code (Martin Fowler, Kent Beck et al.) – The first couple of chapters are a must read for every developer. In those chapters, the book introduces one of my favorite terms in determining the quality of code – smells. There are certain, well, smells that bad code gives off – little things that indicate there’s probably a better way to do things. The rest of the book is a great reference on how to convert that bad smelling code into code that’s more readable and elegant.

Code Complete (Steve McConnell) – While this book may seem very basic at times, it covers basically every item that needs to be covered in every team’s coding standards documents. In fact, it wouldn’t be a bad idea at all to make this book the team’s coding standards.

CLR via C# (Jeffrey Richter) – Want to know what goes on behind the scenes in the CLR? Trying to figure out what’s emitted when you create an anonymous type? Looking for the best way to take advantage of certain .NET features? This is the book for you. This book belongs on the shelf of every .NET developer.

Framework Design Guidelines (Krzysztof Cwalina, Brad Abrams) – The tile of this book is a bit deceptive in my opinion. While this book certainly does spend talking about how best to build libraries, it gives great coverage to best practices in .NET. It’s a very approachable book, categorizing best practices as Do, Consider, Avoid and Don’t.

The Art of Unit Testing (Roy Osherove) – I’m a huge proponent of test driven development (TDD). When done correctly, TDD saves time in the long run, makes for more elegant code, and allows for quick assessment of the state of an application and bugs. However, putting together good tests is a skill just like any other that needs to be learned. This will help get you moving in the right direction.

Keep in mind that all of the above have simply worked for me, and that your mileage may vary. With that in mind, these books come with an absolutely no money back guarantee. However, I do think you’ll find that these will help get you started on your journey and take you to the next level. And even if you’re at that next level, it never hurts to go back to the fundamentals.

Like the list? Don’t like the list? Books you think shouldn’t be on there? Books you think should be added? Let me know!

Friday, November 18, 2011

Taking Advantage of User Profiles

The key to most (all?) successful SharePoint deployments is achieving a high level of user adoption. One of the mail goals of a SharePoint deployment is collaboration, and if a large portion of the user base isn’t using SharePoint, there isn’t necessarily a reason for anyone else to either.

Towards that end, one of the things I look for when it comes to deploying SharePoint for the first time in an organization are little things that I can do for “big wins” – things that are simple for me to set up and configure that my users will hopefully love and help drive them into SharePoint. Implementing user profiles is one of those things.

If you’re not familiar with a user profile, the simplest way to think of it is to picture a Facebook profile. Just like Facebook, users can post status updates, share information about themselves, and find and connect with other people. While at first glance that can seem like a small thing, it actually has many applications throughout your users’ day to day lives.

The most obvious use case for a user profile is simply trying to figure out who someone is. When you’re a larger organization, it’s simply not possible to know everyone. It can be embarrassing to attend a meeting with a senior manager and not realize who that person is. Taking advantage of user profiles to find out who’s participating in a meeting or who’s included in an email can be very helpful.

You may also have times when you need to figure out who works with a particular coworker. I wish I could tell you the number of times I’ll receive an out of office reply without alternate contact information, or the alternate contact is also out of the office. If I am in need of finding someone to get in touch with, I can fire up the person’s profile and see who else works in their department or who their manager might be.

While those are typical day-to-day uses for user profiles, there are other, more subtle, uses as well.

Let’s say our organization is considering implementing a new internal rewards program for sales, or ------. Inviting managers to those planning meetings is pretty obvious, but it could also be good to get input from other employees as well – maybe ones that have been with the organization for a long period of time, or ones that have recently worked for a competitor; they can offer valuable insight. Finding those types of employees in the past would typically require contacting HR and digging up their records. With user profiles, it’s a quick search and I can identify the perfect people to help contribute.

And it even goes beyond direct business needs as well. I’m a big believer that happy employees are productive employees. User profiles can help drive different morale building activities. Users can add personal interests as well, so I can find people that share common passions. Forming a basketball or kickball team can be as easy as looking to see who enjoys those sports. Or, as a runner, if there’s a race coming up I can do a search to find fellow runners to train with, and maybe raise money for a charity as well.

User profiles will quickly become a heavily used resource for your users. It’s a great way for users to connect, find one another for both business and nonbusiness needs, and share information about themselves. Plus, it’s one of those little things that will be a big win (and a big hit) for your SharePoint implementation.