All posts by David Wise

Configuring Reflector in Visual Studio 2008


Red Gate's Reflector (Formerly by Lutz Roeder) is one of those tools that you can technically live without but the question then becomes: why?  It is free and makes SharePoint development that much easier.  And to be honest, those of us doing serious development in SharePoint can use a few breaks in this area.

The main thing that it gives SharePoint developers is the full name of your compiled dll's (including the PublicKeyToken) in the exact format that you have to use all over SharePoint whenever you reference anything in that library. 

The only problem is that Reflector doesn't know where to find your handy DLL, so you have to open Reflector and do File-Open and browse to your newly compiled library.  Except, of course, if you configure it as an External Tool (under Tools on the menu) so that Visual Studio tells it where to find your DLL.  Easy enough.

 

For those who like copy-paste, those arguments are :

"$(BinDir)$(TargetName)$(TargetExt)"

Compiling your project and running Reflector from the Tools menu now should now show you a whole list of libraries with your custom dll at the bottom.  Clicking on your dll name will put information like this at the bottom of the Reflector window where you can then highlight it and copy.  Yes, the information is available simply by looking at the GAC but this is much quicker and less prone to typing errors, and is already in the proper format.

The second thing it gives you, which is actually Reflector's main purpose, is immediate and easy disassembly of a library so you can see the code that is actually being executed when you call functions in Microsoft.SharePoint.dll.  It also opens you up to a whole new world of frustration, as in: “Why in the world did Microsoft not seal a certain webpart class, but then did seal that webpart's custom toolpart class”  Yep. You get to see that stuff too.

Happy reflecting 🙂

SharePoint Advanced Search Scopes Bug


I have a situation where I need to allow a user to pick from a set of available scopes in the Advanced Search box in SharePoint.  In and of itself, this is not a problem as I can configure the Advanced Search Web Part to do this and then customize the specified Display Group as needed.  Easy.  The problem arises when the user attempts to select multiple scopes in the Advanced Search and hits Submit.  Then I get:

“Your search cannot be completed because of a service error. Try your search again or contact your administrator for more information”

It turns out that the problem is that one of the scopes included in the Display Group contains the Scope Rule to include All Content.

The Solution

Create a new scope in your Shared Service Provider that will include all of the content via URL includes and such but does not have the All Content scope rule.  Then update the Display Group used for Advanced Search to use the new scope instead of the original scope. Naturally, the complexity of this option will vary greatly based on your environment.

Note: I cannot take credit for solving this as the original diagnosis and solution is posted here.  I'm rewording it and reposting it here in the hopes of making it easier for people to find as tracking down the original solution took quite a while.  The original solution is also rather technical which may cause non-technical admins to gloss over pretty quickly.

Hidden Gem in GMail Themes


The other day, our good friends at Google introduced Themes for your GMail.  Big deal you say?  Just some new colors?  Think again.  Specifically think more like DreamScene on the web because these themes change.  I don't know about all of them, but I picked “Tea House” last night and it was a night scene with a pagoda and rather peaceful.  This morning, I check Gmail and the same theme is now bright and sunny!

I've been watching it throughout the day and the sun that is on the theme has been moving across the sky with the time of day.  A very cool approach to theming on the web and it makes me wonder what some of the other themes do.

I realize that something like this won't change the world or help anyone make better widgets but it is a new take on what has normally been a rather boring part of the technology scene and that is refreshing all by itself.

Curmudgeon, Revisited


A while back, I mentioned the value of keeping an IT Curmudgeon around the office. Due to recent events, I must now amend that post.

At the time I wrote that, I was working in an office with one and only one such person and immediate evidence matched my past experience.  However, I have now spent two months working in an environment where there were two such people.  Specifically, these two were on opposite sides of me and their preferred method of communication was to yell to each other loud enough to cover the 15 feet that separated them.  You are probably starting to feel my pain now.

The last two months have been spent listening to these two complain about how standards are not what they used to be, Specs are not properly divided in accordance with guidelines from 1985.  The voluminous merits of fixed-width flat files.  Everything in .Net is so much more difficult than it was in COBOL.  Of course, those mainframes and mini’s were laid out so nicely, making it easy to find programs.  Naturally, text editing was far superior on a mini as well.  Oh, and do you remember when the AS400 came out??? Now THERE was a machine that shook the world … and so on … for two months … 8 to 10 hours per day.

If your office is equipped with two or more such people, do not place them in close proximity to one another.  Doing so afflicts all people within earshot with IT Reminiscence Aural Syndrome that cripples morale, creativity and productivity.  ITRAS also can damage hearing as those in nearby cubicles have been known to increase the volume on their IPODs to unsafe levels in the hope of blocking out the non-stop stream of I.T. Tall Tales and Legends.

Make sure that any and all curmudgeons in your organization are separated by as many layers of acoustic insulation as is available.  If they are not allowed to communicate audibly then their overall damage is diminished greatly.   If you won’t separate them for yourself then do it for the others around them.

Inside the SharePoint People Picker


SharePoint provides a handy control commonly known as a “people picker” that allows users to search for and select users defined at some specified scope.  This control is normally associated with Personnel field in a SharePoint List.  However, what happens when you need to add this functionality to some custom component and need to access it programmatically?  It gets a lot more complicated!

Fli5A

This article is meant as more of a repository of knowledge that I’ve discovered while working with this control rather than a “how-to”.  If you are looking for How-To articles, try these: Eric Kraus or SharePoint Tips.   Likewise, please let me know if you have any additional information about the actual workings of this poorly documented control.

Where to find the control

The control is actually called a “PeopleEditor” and is in the ‘Microsoft.SharePoint.WebControls‘ namespace.  You will need to add a reference to ‘Microsoft.Sharepoint.dll’ to your project in Visual Studio, which is something you probably already have if you are writing anything that works with SharePoint.

What is it?

The PeopleEditor is simply a standard UserControl with it’s own hierarchy of elements.  If you were to walk the tree of controls used, you would see the structure shown below  (control IDs are in green italics).

Microsoft.SharePoint.WebControls.PeopleEditor
|-System.Web.UI.HtmlControls.HtmlInputHidden (hiddenSpanData)
|-System.Web.UI.HtmlControls.HtmlInputHidden (OriginalEntities)
|-System.Web.UI.HtmlControls.HtmlInputHidden (HiddenEntityKey)
|-System.Web.UI.HtmlControls.HtmlInputHidden (HiddenEntityDisplayText)
|-System.Web.UI.WebControls.Table (OuterTable)
|- |-System.Web.UI.WebControls.TableRow
|- |- |-System.Web.UI.WebControls.TableCell
|- |- |- |-System.Web.UI.WebControls.Table
|- |- |- |- |-System.Web.UI.WebControls.TableRow
|- |- |- |- |- |-System.Web.UI.WebControls.TableCell
|- |- |- |- |- |- |-System.Web.UI.HtmlControls.HtmlGenericControl (upLevelDiv)
|- |- |- |- |- |- |-System.Web.UI.WebControls.TextBox (downlevelTextBox)
|- |- |-System.Web.UI.WebControls.TableCell
|- |- |- |-System.Web.UI.WebControls.HyperLink (checkNames)
|- |- |- |-System.Web.UI.LiteralControl
|- |- |- |-System.Web.UI.WebControls.HyperLink (browse)
|- |- |- |-System.Web.UI.LiteralControl
|- |- |- |-System.Web.UI.HtmlControls.HtmlInputButton (CreateItem)
|- |-System.Web.UI.WebControls.TableRow
|- |- |-System.Web.UI.WebControls.TableCell
|- |- |- |-System.Web.UI.WebControls.PlaceHolder
|- |- |- |- |-System.Web.UI.WebControls.Label (errorLabel)
|- |- |- |- |-System.Web.UI.WebControls.Table
|- |-System.Web.UI.WebControls.TableRow
|- |- |-System.Web.UI.WebControls.TableCell
|- |- |- |-System.Web.UI.WebControls.Label

Of particular interest are upLevelDiv and downlevelTextBox as those are the controls used when a person is manually entering a name.

Developing With It

The default behavior and styling is sufficient in most cases.  However, if you need to do more than the very basics with the control then I strongly recommend that you subclass it so that you can hook into the control behavior at a much deeper level.  Some of the things you get with this approach are:

  • Control over Formatting.  Microsoft hard-codes much of the formatting in the control and buries it behind protected methods so that you can’t touch it from the outside.  Microsoft applies the style between the PreRender() event but before the SaveViewState() event.  In order to change the style used, you will need to override the Render() event and apply your style changes immediately before the actual control is rendered.
  • OnChange event.  There is none exposed but by subclassing it you can create your own and then hook into the RaisePostDataChangedEvent() method in order to raise your own.
  • Access to the actual controls used.  All of the controls used by the people picker are available as protected properties which means that your subclass has direct access to them without having to walk the hierarchy.
  • Future Changes.  By subclassing this control at the beginning and coding to your new class, you are laying the foundation so that you don’t have to redo tons of code later on in the event that you find yourself needing some of the protected behaviors.

Quirks

  • Normally, you will want to work with the .Entities collection as that has the most information available about a selection but there is a great big “Gotcha” here.  You need to reference .CommaSeparatedAccounts property before calling .Entities because the collection seems to only get populated after that property is referenced.
  • Another Gotcha is that the control will do an Active Directory lookup of all the names you enter in .CommaSeparatedAccounts so it can be a bit of a performance hit – especially if one of those names isn’t in AD.  In my environment, populating this with one valid name takes 0.1 seconds.  Not much, but if you have several of these controls populated with several names then that quickly adds up to real time.
  • The .Entities collection is sometimes null so you have to be careful when working with it.  Given that normal development practices dictate that all public collections exist but have a .Count of zero, I have to assume that this is either developer oversight or an indication of some internal state.  In either case, watch what you are doing when working with this and always check it against null before referencing properties of it.
  • The RaisePostDataChangedEvent event seems to fire whenever the page is posted back a second time even if the value hadn’t changed.
  • Since this is actually a SharePoint control, it expects a few things to be in place – specifically that SharePoint’s “core.js” be included on the page.

Styling the Control

Microsoft embeds the formatting for the control deep inside and then makes use of the .Style attribute rather than the .CssClass attribute which makes styling it somewhat problematic as the .Style attribute will override anything in your CSS.  To make this a little bit worse, this control renders differently in IE than in other browsers like Firefox so you will have to solve styling for both browsers.

Here is what the control renders as in Internet Explorer (I’ve highlighted the key styling areas and their associated class)

Fli8E

Here is how it renders in Firefox.  Note that the resolved user name shown is the Domain ID instead of the user name like in IE.  Also, this is a simple textbox instead of the textbox/div combo that IE uses.

Fli29B

Tracking down what style is used where is made considerably easier with tools like the Developer Toolbar for IE and FireBug for Firefox – both free.  These tools allow you to inspect page elements as they are currently rendered, showing the hierarchy of styles, controls and such.  They are invaluable if you will be doing considerable tweaking to the layout of the People Picker.

Validation

There is an internal validator that allows you to validate the names entered (both on client and on Page Postback) and it works like any other validator in Asp.Net.  You can enable this by setting the .ValidatorEnabled property to “True”.

It is worth noting that this is merely an implementation of the IValidator interface so it cannot be cast as one of the standard Validator types (CustomValidator, RangeValidator, etc.).  This can be problematic if you are trying to work with it via the Page.Validators() collection as the IValidator interface doesn’t really provide enough information to be useful.  In my case, I had to cast it as my subclassed version of the PeopleEditor control and then get the values I needed that way.

Helpful Links