SPExLib Release: These Are A Few Of My Favorite Things

It’s no secret that I’m a big fan of using extension methods to simplify work with the SharePoint object model. Wictor Wilén has allowed me to incorporate many of my “greatest hits” (and some new techniques! more on those in coming weeks) into his excellent SharePoint Extensions Lib project, which added a new release over the weekend (also see Wictor’s announcement).

It’s also worth pointing out that this isn’t just a library of extension methods. It also includes some useful base controls and auxilary classes, including SPDisposeCheckIgnoreAttribute and SPDisposeCheckID with IntelliSense support. If you have classes or methods that you simply can’t live without, we’d love to incorporate them as well.

Additional reading on some of the extensions included:

SPExLib Features

  • Namespace: SPExLib.General
    • Extensions to the .NET 3.5 SP1 Fx
  • Namespace: SPExLib.SharePoint
    • Extensions to the SharePoint object model.
  • Namespace: SPExLib.SharePoint.Linq
    • Linq extensions for the SharePoint object model. Including Linq operations on SPWeb/SPSiteCollection using dispose-safe-methods.
  • Namespace: SPExLib.SharePoint.Linq.Base
    • Implementation of IEnumerable<T> on the SPBaseCollection, which Linq-enables all collections in the SharePoint object model.
  • Namespace: SPExLib.SharePoint.Security
    • Extension methods that simplifies impersonation tasks on SPSite and SPWeb objects
  • Namespace: SPExLib.SharePoint.Tools
    • SPDispose checker utilities
  • Namespace: SPExLib.Diagnostics
    • Debug and Trace features
  • Namespace: SPExLib.Controls
    • Template classes for WebParts and EditorParts

Check it out!

Why You Need Reflector: SPList.DefaultView

I love Reflector. It has been invaluable in my various continuous learning efforts, poking around interesting code to improve my own. However, the need for Reflector spans beyond curiosity: when working with the SharePoint object model, it is an essential tool to understand what’s going on behind the scenes. It would be great if the API always did what you expect, or at least documented some of its less-than-obvious behavior, but it doesn’t and probably never will. It’s simply too big and “what you expect” is often a matter of opinion.

An excellent example is the behavior of SPList.DefaultView. As recently discovered by Andy Burns and earlier documented by Daniel Pavelescu, DefaultView returns a new SPView instance on every call. So instead of this:

list.DefaultView.ViewFields.Add("SomeField");
list.DefaultView.Update();

You need to do this:

SPView defView = list.DefaultView;
defView.ViewFields.Add("SomeField");
defView.Update();

Daniel was able to verify this behavior with the VS debugger, but it’s not clear why. Enter Reflector:

  1. SPList.DefaultView:
    public SPView DefaultView
    {
        get
        {
            return this.Views.DefaultView;
        }
    }
  2. SPViewCollection.DefaultView:
    internal SPView DefaultView
    {
        get
        {
            if (this.m_iDefaultViewIndex != -1)
            {
                return this[this.m_iDefaultViewIndex];
            }
            return null;
        }
    }
  3. SPViewCollection.Item[Int32]
    public SPView this[int iIndex]
    {
        get
        {
            if ((iIndex < 0) || (iIndex >= this.Count))
            {
                throw new ArgumentOutOfRangeException();
            }
            return new SPView(this, this.m_arrViewSchema, iIndex);
        }
    }

In three clicks we see exactly what the problem was and why. Since I usually have Reflector open, this is almost always faster than asking Google or MSDN. Of course some methods are obfuscated (code can’t be disassembled), but fortunately these are exceptions rather than the rule.

Exploring SPView.ViewFields

As another example of code not behaving as expected, consider the implementation of SPView.ViewFields:

public SPViewFieldCollection get_ViewFields()
{
    if (this.m_xdView != null)
    {
        while (this.m_bFullBlownXmlDoc)
        {
            return new SPViewFieldCollection(this, this.Node);
        }
    }
    return new SPViewFieldCollection(this, this.GetInnerXmlForNode("ViewFields"));
}

Given that a new collection is created each time, one might expect the following to add only the second field:

SPView defView = list.DefaultView;
defView.ViewFields.Add("FirstField");
defView.ViewFields.Add("SecondField");
defView.Update();

But, much to my surprise, both fields are added! So what’s going on here? Well, let’s explore a bit with PowerShell:

PS 1> $w = spw http://localhost
PS 2> $l = $w.Lists['Test']
PS 3> $dv = $l.DefaultView
PS 4> $vf1 = $dv.ViewFields
PS 5> $vf2 = $dv.ViewFields
PS 6> $vf1
Attachments
LinkTitle
PS 7> $vf1.Add('Editor')
PS 8> $vf2
Attachments
LinkTitle
Editor

So we store two different SPViewFieldCollection objects, update one, and the other is updated as well. In my mind, this begs two questions:

  1. Why doesn’t SPView just store a reference to a shared collection?
  2. How are the collections kept in sync?

It’s tough to guess why, but Reflector can probably help us figure out how. Let’s start with one of the constructors called by ViewFields:

internal SPViewFieldCollection(SPView view, string innerXml)
{
    this.m_View = view;
    this.m_ViewStyle = null;
    this.m_strInnerXml = innerXml;
}

Not much to see here, other than the captured reference to the parent SPView. Using Reflector’s Analyze function (Ctrl-R), we see that m_strInnerXml is also referenced in the SchemaXml property:

Analyzing SPViewFieldCollection.m_strInnerXml

Which disassembles as…

public string get_SchemaXml()
{
    if (this.m_node == null)
    {
        return this.m_strInnerXml;
    }
    return this.m_node.InnerXml;
}

So the value passed in is only used if m_node has not been set. Ctrl-R again:

Analyzing SPViewFieldCollection.m_node

Now we’re getting somewhere. The members rely on EnsureViewFields() to keep up-to-date:

private void EnsureViewFields()
{
    if (this.m_node != null)
    {
        this.m_iCount = this.m_node.ChildNodes.Count;
    }
    else
    {
        this.m_View.EnsureFullBlownXmlDocument();
        this.InitViewFields(this.m_View.Node);
    }
}

And the node connection is set up in InitViewFields using its view’s Node. So SPViewFieldCollection doesn’t even have an internal data store! Instead, everything operates against m_node, which is attached to the parent view. Thus changes to one collection are immediately reflected in other collections created from the same SPView.

I still prefer to capture and reuse the SPViewFieldCollection, but at least now we know that it’s safe not to and, more interestingly, why that’s the case.

Time to share! When has Reflector saved you from SharePoint headaches?

Add SPDisposeCheck to Visual Studio External Tools

In Episode 16 of SharePoint Pod Show, Todd Bleeker had a great SPDisposeCheck tip that bears repeating: add it to your Visual Studio External Tools!

Tools > External Tools > Add

SPDisposeCheck as VS External Tool

Here’s some output from the included example solution:

SPDisposeCheck Output in VS

My warning against overdependence notwithstanding, this really is a tool that should be run against any object model code.

Of course, Todd had a lot more to say than just this tip, and the whole show is definitely worth a listen. I will disagree on one point though: I wouldn’t consider returning an SPSite or SPWeb from a helper method to be a “false positive”. Sure, you can document the behavior, but it’s much easier to maintain over time if these objects are always created and disposed in the same place (if only because you can use using). I have yet to see an example where this sort of helper pattern couldn’t be refactored out into something more manageable.

SPDisposeCheck Is Not A Shortcut

If you’re a SharePoint developer and you haven’t heard about the release of SPDisposeCheck, there are a number of blogs (like the SharePoint Team) you should be reading instead of (or hopefully in addition to) mine. Everyone is understandably enthusiastic—memory management is important and the rules are tricky. However, I’m afraid this is being viewed as something it’s not. To quote Tony Bierman‘s comment on Paul’s post:

I think there should be a “SPDisposeCheck Certified” logo.  This badge could be placed on the download pages and in the documentation of both free software and commercial software products as an indication of quality and adherence to best practices.

Let’s be clear: SPDisposeCheck is not definitive. It is a static analysis tool tuned to specific rules documented on the often-cited Patterns By Example. That post has been through perhaps a dozen iterations in the last year, updated as recently as last week. The team has no doubt put a lot of work into it (thanks for that), but there’s no reason to expect the guidance won’t be changed again.

Furthermore, there are countless perfectly safe code patterns, the so-called “false positives”, that will be reported as leaks. The documentation cites SPContext.Web.Site as an example, and I could probably rattle off a dozen more if pressed to do so. If the developer doesn’t investigate and just “fixes” every warning with using, more harm is done than good!

The tool will certainly be updated with the latest guidance, and the false positives will be addressed over time, but the core problem still remains: SPDisposeCheck will never know your code as well as you should. I’m sure thousands of leaks will be fixed because of it, and I’m not trying to diminish its value as part of a developer’s toolbox. Just don’t get caught thinking that passing SPDisposeCheck is a substitute for knowing what you’re doing.

That said, a big thanks to Roger, Stefan, Paul and the rest of the SPDisposeCheck team for their efforts to improve their documentation and the quality of our custom code.

STSDev Theme Solution Generator Update

It took a bit longer than expected, but I have finally revisited my STSDEV Theme Solution Generator. I just posted a new release on CodePlex—STSDEV 1.3b with Theme Generator—and the full source is now available in my CodePlex repository. The big theme-related addition in this version is an option to automatically apply Heather Solomon’s @import technique, as a simple checkbox for now. There’s a lot more it could do for us (move other theme assets into LAYOUTS, fix image references in the CSS, etc), but it’s a start. I also fixed a TemplateFiles bug in STSDEV that has annoyed me for a while.

I’m curious what the community thinks I should do with the Generator. If STSDev were more mature, I would just release a Generator DLL for a specific release, but for now it’s still relatively volatile and the APIs I’m using will probably (hopefully, in some cases) change. There’s also the issue of STSDev vs. STSDev 2008. And maybe more importantly, is this even a tool worth maintaining as more than a proof-of-concept? I’m open to your thoughts/suggestions.

Posted in Branding, SharePoint, Tools. Tags: , , . Comments Off

Isolator for SharePoint

With a few exceptions, the SharePoint developer community has been relatively quiet about unit testing and TDD, in part because so much code has tight dependencies on the object model. However, Andrew Woodward recently posted a whitepaper on the subject that caught my eye: Unit Testing SharePoint Solutions – Getting into the Object Model. Featured in the paper is Typemock Isolator, which has just been released in a special SharePoint-only version:

Typemock are offering their new product for unit testing SharePoint called Isolator For SharePoint, for a special introduction price. it is the only tool that allows you to unit test SharePoint without a SharePoint server. To learn more click here.

The first 50 bloggers who blog this text in their blog and tell us about it, will get a Full Isolator license, Free. for rules and info click here.

Posted in Object Model, SharePoint, Tools. Tags: , . Comments Off

STSDEV Theme Solution Generator

SharePoint for End Users just put up up a post about custom themes that echoed the same process that has been repeated several times before:

  1. Log into your SharePoint server
  2. Copy an existing theme
  3. Rename OLDTHEME.INF to NEWTHEME.INF and inside replace OldTheme with NewTheme
  4. Modify TEMPLATE\LAYOUTS\1033\SPTHEMES.XML
  5. Modify theme.css, images, etc.

I like this article in particular because it points out to the “end user” the un/ghosting caveat of SPD customizations that administrators despise and most developers learn on day 1. But it still advises the changes be made directly on the file system, with no mention of how that should be done. Sure it’s an end user audience, but modifying the hive should bump it squarely out of beginner territory.

That said, one of the comments got me thinking:

I have just one question. Is there a way to deploy custom themes as a solution?

Well, we developers all know the answer is yes. I’ve previously discussed updating SPTHEMES.XML, and there are several tools (WSPBuilder, STSDEV, VSeWSS (in theory)…) that can handle “solutionizing” the theme resources, but there has to be a better way. And through STSDEV‘s solution provider interface, there is!

Imaginiff

Suppose getting started on a new theme were as simple as this:

  1. Create Solution
    STS Theme Generator - Create Solution
  2. Pick Theme Template
  3. Enter Theme Details
  4. Solutionized!

The solution provider copies the existing theme, renames the .INF, does the search and replace, and even builds a farm-scoped feature complete with receiver to update SPTHEMES.XML. The current STSDEV release (1.3) doesn’t populate the feature receiver assembly, but after adding that to feature.xml the solution should be ready to customize and deploy.

I need to clean up the code a bit before I put it on CodePlex, but in the meantime you can download the binary here: STSDEV 1.3a with Theme Generator. If you’re new to STSDEV, check out Ted‘s Tutorial Screencasts (scroll down) to get started. And if you have any problems or feature requests, please let me know. One idea that I’m already planning to implement is an option to convert a theme to use Heather Solomon‘s @import technique.

Update 12/11/2008: An updated release is available here: STSDEV 1.3b with Theme Generator

Follow

Get every new post delivered to your Inbox.