Hey – we’ve all made mistakes.  We all know that “oh sh**” moment right after we realize what we’ve done.  Often times this occurs right after we click a friendly “Are you sure??” dialog.  Of course I’m sure – if I wasn’t sure I wouldn’t have chosen to do it in the first place!  Stupid computer.

Anyway, I recently had a situation where someone (honestly, in this case it wasn’t me) accidentally deleted the Site Collection for the SSP admin site (/ssp/admin).  Since this was for a SharePoint farm in production I really didn’t want to have to re-create the entire SSP but I couldn’t figure out how to just re-create the site collection itself.  I figured there had to be a site template for the site but since it didn’t show up in the Create Site Collection UI I went and looked on disk.  Sure enough, a site template exists for the SSP Admin site.  It’s called OSRV.

So to create a new SSP admin site, run this command line.

stsadm.exe -o createsite -url http://<server>:<ssp_port>/ssp/admin -owneremail <email address> -ownerlogin <account> -sitetemplate OSRV#0 -title "Shared Services Administration: <your ssp name>"

This might take a little while to complete, but it does eventually finish.

Next you need to edit the SSP to point to the recreated site.

stsadm.exe -o editssp -title "<your ssp name>" -sspadminsite http://<server>:<ssp_port>/ssp/admin

That’s it.  You should be back up and running.

SharePoint? Meet Python

August 12, 2007

Ever have a need to quickly script some administrative task relating to SharePoint? Ever wish there was more you could do with STSADM? Ever wish you had an interactive console for exploring the object model and testing various methods or properties? Well Iron Python is your answer. In this short article I’ll show you how to get up and running with Iron Python and SharePoint. I’ll also show you a few scripts that will give you some insight into the potential power of this extremely useful combination. Read the rest of this entry »

Site Templates

June 20, 2007

I hate searching for this stuff every time I need it.  So here is a list of SharePoint site templates and their friendly names.

Friendly Name Template
Team Site STS#0
Blank Site STS#1
Document Workspace STS#2
Wiki Site WIKI#0
Blog BLOG#0
Basic Meeting Workspace MPS#0
Blank Meeting Workspace MPS#1
Decision Meeting Workspace MPS#2
Social Meeting Workspace MPS#3
Multipage Meeting Workspace MPS#4
Document Center BDR#0
Records Center OFFILE#1
Personalization Site SPSMSITE#0
Site Directory SPSITES#0
Report Center SPREPORTCENTER#0
Search Center with Tabs SRCHCEN#0
Search Center SRCHCENTERLITE#0
Publishing Site CMSPUBLISHING#0
Publishing Site with Workflow BLANKINTERNET#2
News Site SPSNHOME#0

I recently did some load testing for a client and needed to populate our environment with sample data to simulate real-world usage.  This was my first occasion to use the tools released on Codeplex for this – WSSDW and MOSSDW.  As I was stumbling through the semi-documentation and samples that didn’t really work I started jotting down some notes.  This is a collection of these lessons learned – hopefully they’ll help someone else avoid some of the “WTF” moments I had 🙂

Download both WSSDW AND MOSSDW.
I ran into a ton of problems when I started because I only downloaded MOSSDW.  The samples don’t work without WSSDW – WSSDWLib.dll to be exact.  So download them both and install them in the same folder. 

You need to “Unblock” the help files (chm) before you can read them.
After downloading the help files, right-click, choose properties, then click Unblock.

Don’t bother trying to delete sample content. 
The tool just doesn’t work very well.  You’ll end up with an error and a bunch of left over content.  The best thing to do is just to create your sample site hierarchy under a single “Test” web and then just delete the Test web manually (or with stsadm) each time.  Note, you may have to use the Manage Site Content and Structure UI in MOSS so that you can delete webs with subwebs.

Creating a publishing page and publishing it is a two step operation.
This just seems weird so maybe I am missing something.  But if you want to create a publishing page, add content to that page, and publish it, you need two XML node actions.  The first node creates the page and adds content.  The second node publishes it.  For example:

<TestPage Name="Page1.aspx" PageLayout="ArticleLeft.aspx" openmode="modifyexisting">
  <TestHtmlFieldValue Name="Page Content" HtmlFile="MOSS_Intro.htm" openmode="modifyexisting"/>
</TestPage>
<TestPage Name="Page1.aspx" openmode="modifyexisting" Status="Published" />

You would assume you could just add the Status=”Published” bit to the first TestPage node.  But what happens is that the status gets set before the TestHtmlFieldValue node is parsed – so this action fails because the page isn’t checked out.  *rolls eyes*

Mixing and matching MOSS tags and WSS tags has some issues.
If you’re going to mix and match MOSS and WSS tags, be sure to use WSS tags to walk your web hierarchy.  The <TestArea> MOSS tag won’t provide context to children such as <Lists>.

Agile is THE ONLY way to build SharePoint applications.  Pure and simple.  If you think otherwise, sorry.  You are wrong.

Oh… you wanted an explanation?  Okay – here you go.

I could bore you with a bunch of background on Agile and what’s good about it, what the process is, what the core concepts are, etc.  But I won’t.  If I did that we would just go back and forth forever on the benefits/shortcomings of Agile development.  Instead I’ll get right to the point.

You do not know enough about SharePoint to fully spec a solution end-to-end.

Let me repeat that.  YOU (yes you), DO NOT know enough about SharePoint.  I know you think you do.  I know you think you know how everything works, how everything fits together, but you don’t.  And you know what?  Nobody does.

There you go.  Any application you want to build that has any level of complexity just cannot be fully designed up front.  There are too many unknowns at every level in the product.  Too many assumptions need to be made about what should work.  And we all know that there are dozens of unanticipated gotchas waiting around every turn.

SharePoint 2007 is a huge product.  It has a ton of little nooks and crannys each providing great functionality, but also hiding pure WTF, “why did they do it that way”, suprises.  SharePoint is just too big and too new for anybody to know it intimately enough to fully define a solution end-to-end without actually doing some trial and error implementation.  So if you’re doing trial and error implementation anyway, why not include the client and make them short iterations?

Okay – a few more quick benefits to this approach:

  1. Don’t have to spend time documenting out of the box functionality that you don’t have control over anyway
  2. Wireframes and UI designs are less critical because you can “design” on the fly using the out of the box UI – then identify the gaps where additional design elements or controls are needed
  3. End up with less code/customization because once users see it out of the box, they quickly reach a “good enough” point.  You can focus your customizations where where adds real value.
  4. The very nature of letting the user touch and feel the solution will change their requirements.  They will realize that certain things are less important than they thought while others are more important.  This is true with any application development but the fact that you can do so much out of the box in SharePoint means you can get to this point very very quickly.

So there you go.  Good luck.  We have a tough fight ahead of us convincing people that SharePoint is different enough to warrant throwing old waterfall methodologies away and trying something new.

Motivation

May 1, 2007

I’ve got good news and bad news. First the good news: as a manager, having motivated employees is completely within your control. It doesn’t matter how big your budget is, how many employees you have, or how high in the corporate food chain you are. It is absolutely within your power to have motivated and enthusiastic employees.

Now the bad news: having motivated employees is your responsibility – yours and yours alone. It’s not the responsibility of the HR department or some disconnected “Chief Culture Officer”. It is your responsibility. And it gets worse – if you want to motivate your employees, you have to mean it.

So, before you read any further you need to ask yourself a question: do you feel motivated? Do you want to motivate your employees? Do you want to motivate your employees because you want them to feel the same commitment and passion you do? Or because you want to squeeze a few more hours out of their already long work day?

Motivation is all about communication and vision. It’s about transferring your own motivation and drive to your employees. If you don’t believe in the vision, then no amount of “employee retreats” or “team building exercises” are going to make a difference.

So again, ask yourself if you really feel it. If you don’t, it might be a good idea to step aside so someone who is truly motivated can take the reins. On the other hand, if you are motivated and are looking for some tools to help you transfer that motivation to your team, please keep reading.

Still here? Okay well either you’re lying to yourself, you’re really bored and are reading anyway, or you really do feel enthusiastic and want to pass some of that along. Hopefully it’s the latter, but I’m not going to be picky.

I’ve broken this article into four parts:

  1. Being Available
  2. Empathize, to a point
  3. Commitments
  4. General conduct

Part 1 (Being Available) is ready to go now. The other 3 parts will be posted as my time allows.

Being Available
Or, how I learned to get up off my ass and walk around a lot

As I said up front, motivation has a lot to do with transferring your enthusiasm to your employees. But in order to do this effectively you have to be genuine about it. If you aren’t feeling it, you’ll end up doing more harm than good. Employees only need a few “fake” ra ra sessions to start seeing everything you do in that light. So the best thing to do if you aren’t feeling the enthusiasm is to do nothing. Doing nothing is much better than doing something in this case because that something is likely to cause damage that is very difficult to undo. Read the rest of this entry »

I’m on a mission. And that mission is to build SharePoint apps without dropping code on the server. Why would anyone want to do this? Well, in many enterprise or hosted environments you don’t have the ability to drop DLLs into a shared SharePoint environment. This has often limited the types of applications we can build to out of the box features or SharePoint designer. But with some Javascript and the WSS web services, we can build a more complex app all with AJAXy goodness.

This code sample uses the Prototype Javascript library. When you see Ajax.Request, that’s using prototype’s Ajax framework. The great thing about prototype is that everything is cross-browser compatible.

First we need some code that formats a simple SOAP envelope. SOAP is the required protocol for communicating with the SharePoint web service.


var Soap = {
  createEnvelope: function(action, ns, parameters)
  {
    var soap = '<?xml version="1.0" encoding="utf-8"?>
        <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
        <soap12:Body>';
    soap += '<' + action + ' xmlns="' + ns + '">';
    soap += Soap.__parseParameters(parameters);
    soap += '</' + action + '></soap12:Body></soap12:Envelope>';
    return soap;
  },

  __parseParameters: function(parameters)
  {
    var params = "";
    if (typeof parameters == 'object')
    {
      // check if we were provided an array or an object
      if (typeof parameters.push == 'function')
      {
        for (var i = 0, length = parameters.length; i < length; i += 2)
        {
          params += "<" + parameters[i] + ">" + parameters[i+1] +
              "</" + parameters[i] + ">";
        }
      }
      else
      {
        $H(parameters).each(
          function(pair)
          {
            params += "<" + pair.key + ">" + pair.value + "</" + pair.key + ">";
          });
      }
    }
    return params;
  }
}

Okay, so now we can make a SOAP envelope as simple as this:

var mySoap = Soap.createEnvelope(
  "MyAction",
  "http://schemas.microsoft.com/sharepoint/soap/",
  { param1: "value", param2: "value" });

Simple enough. Now let’s call a SharePoint web service. We’ll use the Lists web service and create a new list item. The UpdateListItems method allows us to pass in some XML defining the items to create. So first I’m going to build that XML.

var batch = '
  <Batch OnError="Continue">
    <Method ID="1" Cmd="New">
      <Field Name="ID">New</Field>
      <Field Name="Title">Hello World</Field>
    </Method>
  </Batch>';

Next we’ll call the web service using the Ajax.Request object:

// build parameter object
var parameters =
{
  listName: "My List",
  updates: batch       // xml created earlier
}

// create soap envelope
var soap = Soap.createEnvelope(
  "UpdateListItems",
  "http://schemas.microsoft.com/sharepoint/soap/",
  parameters);

// call web service
new Ajax.Request(
  "http://myserver/mysite/_vti_bin/lists.asmx",
  {
    method: "post",
    contentType: "application/soap+xml",
    postBody: soap,
    onSuccess: function(transoprt) { alert("Success: " + transport.responseText); },
    onFailure: function(transport) { alert("Error: " + transport.responseText); }
  });

If all goes according to plan, I should have a new list item with the title of “Hello World” in the list called “My List”.

A couple of points about the javascript above:

  1. It’s certainly not the greatest Javascript in the world. I plan to clean it up and hopefully release a Javascript library for working with all of SharePoint’s web services.
  2. The user’s browser must already be authenticated for this to work. Prototype doesn’t have a way to pass credentials to the web service so make sure you run this from a machine joined to the same domain as the sharepoint site. Ideally this is running within a sharepoint site so that should take care of the authentication problem.
  3. FireFox has an issue because it doesn’t pass domain credentials automatically. This makes debugging hard from your workstation, but if it’s running on a SharePoint site where the user has already authenticated, it works fine.
  4. I cheat in the example above and break strings onto multiple lines. That’s for the purpose of formatting only. If you copy and paste this code directly it won’t work.

You can download the code here: wsswebservice.js.

Well, I’ve been skeptical about what Google is trying to do. I love Gmail but I’ve held off really trying out their other products. But recently I was running a beta of Excel 2007 and it expired so I was left without a spreadsheet program. I decided to give Google spreadsheets a try.

At first I got what I expected – much of Excel’s basic functionality while feeling a little less responsive than a desktop app. I mean, for a web app they’ve done a remarkably good job, but it’s still not the same as a rich desktop application. But then I discovered two excellent features that I didn’t expect.

The first came after I had been working on a spreadsheet for a while and realized that I had it so screwed up I wanted to go back to the beginning. I was just about to close and re-open the spreadsheet when I noticed the “Revisions” tab at the top. I clicked on this and – hey what do you know – just about every change I made was automatically saved as a revision. I flipped through the revisions, found the place I wanted, and overwrote my f’d up version with a clean version. Now that’s something you don’t get in Excel.

The next thing that happened (which prompted me to write this blog post) is that I was making a change when all of a sudden I lost my internet connection (damn netgear wireless crap). Now I’m thinking “ugh – lots of rework” but all of a sudden Google pops up a little box that says “uh hey – you don’t have connection. you want to work offline or try and reconnect?”. Wow – ok, let’s see how this works. I reboot my router, get my connection back, click the “try and reconnect” option, and I’m back and running. No lost data – nothing. Everything is exactly as if I had never lost connection in the first place. Now that’s slick!

So I’m not sure if I’m completely sold on giving up Excel but I have to say that if Google keeps going the way they are going with innovative features and solid design, I might just be tempted.

MicroISVs and their blogs

February 4, 2007

It seems like every small software company out there has a blog these days. It’s become a requirement. In fact, most times these days the blog shows up before the actual product. But if you ask me, by and large it’s a waste of time. If you’re blogging in the hopes that it will attract potential customers or keep customers interested then you need to look long and hard at the kind of content you’re publishing.

Look, marketing is important – critically important to the success of your company. But if your blog is going to be a marketing tool, it’s got to be targeted at your potential customers. Your customers don’t care that you really liked some Joel on Software post. Your customers don’t care that you’re putting the finishing touches on some feature or that you contributed to some open source project over the weekend. Your customers want to read things they care about – not things you care about.

The key to a successful blog for a software company is one that truly provides value and connects with your customer base. If you are passionate about the subject of your software, then you have a good chance of writing a compelling blog which adds value on top of the software you sell. If you’re not that passionate, or if you suck at writing, a better approach would be to try and aggregate news articles or other industry/subject related blog postings.

At the end of the day, look at everything you do through the eyes of your customer. Is it valuable to them? If not, then you should stop and put that valuable time into something else.