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 on STSDev Theme Solution Generator Update

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 on Isolator for SharePoint

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

Another SharePoint Developer/Debugging Tips List

If you can only follow a single SharePoint developer blog, it should probably be Andrew Connell (even if hitting Enter in his Search box still doesn’t work in Firefox). If for some reason you haven’t already, make sure you’ve read his excellent SharePoint developer tips and tricks and SharePoint Debugging and Logging Tips and Tricks. Here are a few additional tips from comments there and elsewhere:

Debugger.Launch()

AC suggests System.Diagnostics.Trace.Assert(false) to force the debugger; System.Diagnostics.Debugger.Launch() is a more explicit alternative (featured on Corey’s .NET Tip of the Day).

Debugging GAC’d Assemblies

AC says “you’ll need to put the debugging symbols in the same location as the assembly.” While a few of the comments hint that for them it “just works” without that step, that’s probably due to a setting in their environment: Just My Code debugging is likely off. Vincent Rothwell’s Debugging Tips for SharePoint mentions this setting in passing and it has since been highlighted here and here as well.

Attaching to w3wp

Debugging doesn’t work if you aren’t attached to the right IIS worker process. One option is to use the Debugger Feature from the CodePlex Features project, which adds a new menu item to the Site Actions menu that attaches the debugger. If you would rather not install a feature, Doug Perkes suggests adding a VS External Tool to list the PIDs:

  • Title: Get IIS PIDs
  • Command: cscript.exe
  • Arguments: %systemroot%\system32\iisapp.vbs
  • Check “Use Output Window”

More External Tools

Speaking of which, Scot Hillier has put together a CodePlex project to support his development process. The installation includes several useful External Tools and more than a dozen developer-focused STSADM extensions. My favorites are enumpools and recyclepool; much more SharePointy than iisapp.vbs /r /a. Or for a GUI try Spence Harbar‘s Application Pool Recycle Utility for SharePoint Developers. For even more STSADM extensions (and some great SP object model code in general), check out Gary Lapointe’s blog.

Opening WSPs

Some developers prefer to make a copy of their WSPs with a .CAB extension as part of their development process, but if you don’t mind modifying the registry Waldek Mastykarz has a nice post on browsing .wsp files using Windows Explorer. Or if WinRAR is your tool of choice, a .reg with the following will do the trick:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.wsp]
@="WinRAR"

Easy Access to 12 and VirtualDirectories

Waldek also posted about getting quickly to the VirtualDirectories folder in Explorer View. Many developers use a 12 Hive Toolbar; I use the same technique for VirtualDirectories. As for opening in Explorer View, why not make that the default Folder action? Here’s another .reg that does just that:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Folder\shell]
@="explore"

Managing CAML

If I don’t stop myself now I’ll end up with a comprehensive list of every cool SharePoint thing I’ve seen in the last year. So I’ll leave you with Katrien’s list instead.

Update 7/12/2008: Added U2U CAML Query Builder.

VSeWSS: At Least It Knows CAML

Scot Hillier just posted an excellent answer to the question “Is VSeWSS 1.2 Ready for Prime Time?” In the comments, Microsoft’s Chris Johnson follows up with the assertion that the extensions cover 99% of what a developer might need. I would put that number a bit lower, but more important is the first impression given by the tools.

As the logical first tool for new developers, the extensions will undoubtedly play a formative role in how that developer thinks about SharePoint development. Scot highlights one such problem in the provided project templates: two of the four (plus empty) are Site Definitions. To a new developer, this implies that Site Definitions are probably really important, when in fact you (probably) don’t need them.

Another fundamental shortcoming of the extensions is the black box method of solution creation. Managing DDF files and manifest.xml can certainly be tedious, but there comes a time when every developer needs to tweak something in the solution definition. Scot’s example is the forced inclusion of an assembly; a quick glance at the Solution Schema reveals several others (SafeControls and CAS in particular). This is a huge blind spot in a new developer’s understanding of how SharePoint really works.

Update: A bit more research reveals that you can indeed add SafeControls (example by Chris Johnson) and CAS to the manifest.xml in WSP View. Better examples might be RootFiles or Resources, which don’t seem to have anywhere to go in a VSeWSS project.

Less prevalent but equally disarming is that the project just ignores files that it doesn’t understand. I had originally planned to use the branding lab of the VSeWSS-based SharePoint Hands on Labs (download) as an example for my latest post on using features to update SPTHEMES.XML. The process went something like this:

  1. Open VSeWSS project
  2. Add New Item > Module
  3. In new feature: Add Existing Item > Browse to SPTHEMES.XML
  4. Switch to WSP view and update the feature.xml with the new <ElementFile />
  5. Deploy
  6. Error: Cannot find this file specified in the manifest file:
    NewBrandTheme\NewBrandTheme\SPTHEMES.XML
  7. Sigh…

Missing ElementFile
The only way I could get my file included in the solution was to add it to the module:
<File Path="SPTHEMES.XML" Url="ThanksVSeWSS" />
Which has an undesired side effect:
Thanks VSeWSS

Ultimately the problem comes down to the tool not allowing someone that knows better to take control. A bike with permanent training wheels is eventually outgrown.

As A CAML Tool

Specific limitations aside, Chris did hit on a very important use of the extensions: heavy lifting of the XML files. I have found no better way to generate the extensive XML required for List Definitions Templates, Content Types and such. (For more help authoring XML, check out AC’s tools.) New developers in particular should use the extensions to build a few content types, lists, instances, etc. to see how everything fits together. But what if we want to use these XML files with another solutionizing method (WSPBuilder, STSDEV, PowerShell, batch files)? We could certainly retrieve them from the 12 hive after deployment, but it turns out there’s an easier way.

When a VSeWSS project is deployed, it stores the full directory structure of the WSP in $(TargetDir)\solution. All we need to do is pull the appropriate folders into a new project built with the tool of your choice: LAYOUTS, IMAGES, etc. into TEMPLATE; feature folders into TEMPLATE\FEATURES; and so forth. Note that the solution directory only stays populated if the deployment succeeds, and you will need to retract the VSeWSS solution (or change the feature IDs) before you can install the features as part of the new solution. Just like SPD, we use the tool for its strengths and then pull what we need out into a project of our own design. I imagine a similar approach could probably be used with WebParts, though I haven’t done anything with them in VSeWSS.

Ultimately I have to agree with Scot that, despite tremendous potential for future releases, for now VSeWSS just doesn’t quite have the flexibility needed for sophisticated solution development. That said, it’s very solid in its strengths and definitely has its uses in the context of your chosen development approach.

Posted in SharePoint, Tools. Tags: . 3 Comments »