Thursday, February 01, 2007

Overriding Default Stylesheets in SharePoint 2007

Heather Solomon posted a detailed explanation on her site regarding the inheritance of styles in MOSS; specifically, the various methods for overriding CORE.CSS in master pages and site definitions. After defining the various options, Heather recommends the following for applying custom styles:

My recommendation is to store styles in the master page itself in a set of STYLE tags. If your master page design has variations for assorted subsites, store the CSS differences in a file and reference it via the Master Page settings, or if you need CSS changes for a single page, store it in an HTML file and reference it in a hidden Content Editor Web Part.

I wasn't at all comfortable with this approach, not so much because there is anything wrong with it (there isn't and Heather should get an award for incurring the brain damage required to sort through it all), but mostly because I don't like the idea of SharePoint forcing a default style onto my customized pages, thereby making me jump through hoops to correct a deficiency that never should have been there in the first place. I thought we'd been through this enough with 2003 and the design team would have learned their lesson but apparently not.

So after playing around with a few alternatives, I went old school and found the solution. Instead of using one of the new < SharePoint:CssRegistration / > tags to register your override style in the header, simply place it in a classic ASP < link > tag in the same location, like so:

< link rel="stylesheet" type="text/css" href="../../Style Library/en-us/Core Styles/core_override.css" / >

This procedure will circumvent whatever the parser is doing in the background to throw CORE.CSS into the mix at all the wrong places. The beauty of it is that CORE.CSS is called before your override stylesheet so you can inherit all the default styles and only override the styles you need. Be sure that the relative path is correct for the site definition you are working with. An alternative would be to place your override into the same folder as CORE.CSS and use a fixed path, which would make working with different site definitions much easier, as each master page can point to its own override file (this can also be done programmatically).

UPDATE: As Shane points out in his comments on this post, using the alternate style setting in the site collection settings IS a reliable method for overriding CORE.CSS; however, there are some things you should consider if you are using this approach:

1) The alternate CSS setting is GLOBAl for the site collection. This means that all pages, including _layout pages, will inherit this style. That may work for one implementation and not another; you might want different styles for the Admin pages (my term for all the pages found in _layouts), content pages, or subsites.

2) The Alternate CSS setting applies to all subsites in the collection, making it more difficult to assign those styles programatically. If you want to mix and match styles in your subsites you will have to find a method to override both CORE.CSS AND the alternate style.

3) The alternate setting must be done AFTER the site is provisioned. This obviously won't work for custom site definitions. A better approach would be to put the style in the master page settings, the PlaceHolderAdditionalPageHead, or, as I have suggested, use a <> tag.

Saturday, January 20, 2007

SharePoint 2007 and the .NET 2.0 Object Data Source

One of the smartest SharePoint gurus I know is Sean Skinner. Lucky for me, he was guillable enough to be fooled into coming to work for my company, so now I get to take advantage of all his know-how on a daily basis. Like, for example, when one of our SmartForms apps blew up all over the place, and we couldnt' figure out what in the world was going on, Sean kept at it until he had the answer. From his blog:

You cannot have an Object Data Source running on MOSS and it have a parameter (insert, update or otherwise) with a type of 'object'. This appears to be the type assigned for GUIDs (database fields of type 'unique identifier'). When you do, as soon as I would bind the formview I would get a generic MOSS error page. You know the one, 'A web part is causing a problem....'By changing the type on the parameter to 'string' everything started working...


(BTW, when he refers to ASP:Table elements junking up otherwise working code inside of SharePoint, what he really means to say is "Eric screwed up my perfectly functional code by filling it up with server-side elements that we didn't need". Now you know the rest of the story...)

There'll be a whole lot more where that came from when we get all of our blogs moved over to the new MOSS site so stay tuned - and if you don't read Sean's blog already, you're missing out. Add it to the 'ol blogroll, pronto!

Tuesday, January 16, 2007

Tag, I'm It!

I was harboring secretive dreams that the recent spate of tagging would leave me unscathed but my hopes have been shattered. Friend and fellow powerblogger Heather Solomon got me at last. So what are five things that people don't know about me that aren't either a) embarrassing or b) still subject to a statute of limitations? How about these:

  • My primary intellectual hobby is ancient Egyptian history. I've read dozens of books on the subject, seen every documentary ever created, visited nearly every major museum with an Egyptian exhibit, and can even read and write some hieroglyphs. As an offshoot, I've also studied a tremendous amount of early Judaic and Christian history as well. If you value your sanity, don't ever get caught near the British Museum with me around or you'll end up losing an entire day of your life to my endless chattering about the proper pronunciation of Tutuanhkamun and why I think Zahi Hawass is an idiot. Unfortunately, I've never had an opportunity to visit Egypt in person but it's on my list of first things to do when I eventually take a vacation (yeah, right).
  • My favorite activity is training and hunting with my Labrador Retriever. If you're not an animal person, you just won't get this, but there is nothing more rewarding than the bond between human and dog when engaged in a singular activity. Cheyenne, my 100-pound black Lab, is an amazing creature - watching her do what she was bred to do is a wonder to my eyes. I spent two years learning about training hunting retrievers before I got her and I trained her myself from the time she was five weeks old. I took a chance and didn't buy her from a breeder (no reason to invest that kind of money if you're not sure of your own skills) but boy did I get lucky - she can hold her own against any of those pedigreed wondermutts you see on TV. One thing I've learned from her that has served me well is that a good dog doesn't need to be trained to work with a person - the person needs to be trained to work with the dog. The dog was born knowing what to do, it's us humans that get things all screwed up. Take that for what it's worth.
  • I'm part Scottish and part Native American (Mescalero Apache). My mother's family is Scottish down to their kilts. My uncle used to be one of the premier bagpipe instructors in the country and my cousin has played the pipes live for Rod Stewart on several occasions. Our line goes back to one of the oldest highland clans, the Atholl Murray's, and one of our ancestors came over on the Mayflower. My paternal grandmother is full-blooded Apache Indian. Unfortunately, all her birth records were lost in a fire years ago so we can't trace back our heritage on that side. And yes, I can drink me some whisky, in case you were wondering :-)
  • I play the harmonica. Or, rather, I did, then I gave it up, then I picked it up again, and now I can barely play the thing anymore. I keep threatening to take it up again but the rolled eyes around my house indicate that I may need some serious refresher courses before I'm allowed to blow any riffs around the 'ol campfire.
  • I used to sell floorcovering. At one point when I was living in California I got burned out on the technology business and went to work selling carpets, wood floors and tile. I did pretty well and actually had a good niche doing custom wood floors and high-end commercial projects. I even learned how to tear it up, install it, do finish work, everything. About as far from high-tech as you can get but at the time that was the whole point. It was fun but I don't think I was cut out for it - I kept finding excuses to play with company's computers and not rearrange my samples on the sales floor. Ah well, once a geek, always a geek!

So there you have it - more than you ever wanted to know about this humble SharePointer. Everyone on my list has already been tagged, so I guess I'm a 'dead end', so to speak. Hey, the chain had to end somewhere, didn't it???

UPDATE: Turns out there are a couple of people who have been flying under the tag radar and need a good one slapped on 'em:

Sean Skinner
Nick Swan

You're it!!!

Tuesday, January 02, 2007

Happy New Year!

To all my readers around the world, I want to wish you a safe and prosperous New Year.

First, I'd like to thank everyone who reads and contributes to this blog. I started blogging in 2005 to share my thoughts with other SharePointers and I never dreamed that I'd be collaborating with people all over the world would. Last year more than 23,000 visitors read this blog and more than 60,000 pageviews were generated for readers in more than 20 countries. Sure, Bil and Jan and AC get more traffic but it's not bad for a country boy from Texas.

Second, my apologies to those very same readers for not posting more often in 2006. Business exploded this last year, leaving me with little time to sleep or eat, much less post regularly. I plan to correct that this year by setting (and sticking to) a regular blogging schedule.

Finally, the new year brings new changes. The eGroup started as a one-man SharePoint consultancy but has now grown by leaps and bounds, with some great new team members coming on board, new offices opening in the UK, and lots of other positive developments. To reflect these changes, we'll be changing our name and launching a new site soon (built on MOSS, of course). With more exposure comes more responsibility, so we'll be releasing more products, tools and utilities throughout the year and participating in events and conferencese throughout the US and Europe (I'll finally get a chance to meet many of you face to face for the first time - hoorah!).

As part of these changes, this blog will be moving to our MOSS web farm and off of Blogger. Not that Blogger hasn't done its job but with the new blog templates in MOSS there's just no reason not to switch. The good news is that all of our consultants and developers will be blogging on the new site so there will be lots of fresh new ideas and solutions. Links to all the new blogs and sites will be posted soon.

I look forward to a very exciting 2007.

Happy SharePointing!!!

Monday, November 27, 2006

Looking For A Few Good SharePointers

It's that time of year again - no, I'm not talking about jolly 'ol Saint Nick, annoying crowds at the mall or an XBox in your stocking (hint, hint), this is even better - The eGroup is hiring! If you've got SharePoint development experience and you're itching to work with a dynamic team of fellow SharePoint-crazy codeslingers, mosey on over to our job postings and see if you fit the bill. No, you won't a free Tesla Roadster and you'll have to bring your own Aeron, but you will get to work on exciting client projects using the latest and greatest Microsoft technologies. Give yourself a Christmas present and tell the boss man you're movin' on up!

UPDATE: UK readers take note - we'll be hiring on your side of the pond in the first quarter of '07. We'll be looking for both experienced and junior SharePoint developers so send in your CV if you'll be in the market for a new gig after the first of the year. In fact, if you're in and about London, drop by the SharePoint UK User Group Meet Up on December 14th (you are a memeber, aren't you?) and introduce yourself (I'll be the only 6'5" Texan in the pub - pretty easy bloke to pick out of a crowd).

Monday, October 23, 2006

SPSiteDataQuery vs. GetListItems

Mart Muller over at TamTam posted his thoughts about using the new SPSiteDataQuery object in MOSS 2007 to retrieve items in a document library without tripping over the annoying folder limitations of the much-maligned SPQuery class. This is handy method for getting list data via the object model but it also has some limitations and 'gotchas' to be aware of.

First, when retrieving list data, anecdotal tests have shown (and our experience has proven this to be absolutely true) that the object model is best suited for working with smaller data sets within web parts or controls in small to medium traffic environments (~10,000 users). Why is this? Nobody seems to know for sure but I suspect that it has to do with the overhead related to repeatedly calling the core DLL's that are also performing a number of other concurrent tasks (but I could very well be wrong; the cause may be up for debate but the results speak for themselves).

Second, as Maurice Prather and Bil Simser have pointed out here, here and here, all those SPSite and SPWeb objects you're throwing around in your code don't dispose of themselves - you have to handle that yourself (you are disposing of your garbage, aren't you?). Those little guys riding round on the back of the Garbage Collector truck never see those objects so they don't throw 'em on the rubbish pile - leave a few thousand of those things open and your application pool will come to a screeching halt.

Third, you have to keep a careful eye on that ViewFields element (and don't forget to write your query correctly). A blank value will return all the fields that the records have in common but not any fields that have blank or null values - these are omitted from the results. This is important when you're looking for a particular field only to discover it's not there at all - crash goes your code. Pass in a null value and you get the default view (such as AllItems.aspx) which may not contain any of the fields you're looking for. You have to specify ALL of the fields that you want to appear in the results. And, just to keep you on your toes, make sure to use the DisplayName value of the column in each < FieldRef > node and not the Name value (they are often quite different, especially in custom lists).

Finally, remember that object model methods of this type are always subject to the annoying but ever-present impersonation issue. Call SPSiteDataQuery in the wrong user context and you won't get very far. RevertToSelf, anyone?

Personally, I prefer to use the web services GetListItems() method to get items from a list because a) it's faster (I know, you don't believe me, but it's true - someone somewhere did a performance comparison once but I can't seem to find it again. UPDATE: Found it here but there aren't any hard metrics in the post. UPDATE II: Scroll to the bottom of this post for some very basic metrics), b) I have more granular control over user credentials (I can use an admin account to get the items then check the user perms to verify the access level - no impersonation required), c) the data is returned as an XMLNode object, and d) there's no garbage to worry about - once the TCP connection is closed the memory is released. Most importantly, the web services scale well, especially in shared services environments where you may have one portal context accessing list data from another portal context. That being said, I will probably use the SPSiteDataQuery object in one-off web parts where scalability and performance are not an issue because the code is short and sweet - which is an advantage unto itself, now isn't it?

Thursday, October 19, 2006

New Article on Custom Master Pages

I get a lot of questions from readers and clients regarding deployment of custom master pages in MOSS 2007. There are several ways to tackle this problem and here's a very good place to start - Heather Solomon's new article on How to Create and Store Master Pages on the Server for Use with Site Collections. Heather is one of my all-time favorite MVP's (I swear someday I'm not going to be neck-deep in projects during a SharePoint conference and we'll actually meet in person) and if you're not reading her blog on a regular basis then you're missing out. Go check it out and get those custom master pages going.

Wednesday, October 11, 2006

To < Query > Or Not To < Query >, That Is The CAML Question

If you do any development using SharePoint's web services you've undoubtedly run across the evil CAML beast rearing it's ugly head to devour your nicely structured markup. For instance, if you invoke GetListItems() to retrieve the column values of each item in a list, you have the option of passing in a CAML query to return specific records or a blank value to get the whole enchilada. The SDK is quite helpful, as it documents how this specific query should look. If, for example, you want a particular record with the title "Yellow", provide the following CAML:

<Query><Where><Eq><FieldRef name="Title"><Value Type="Text">Yellow</Value></Eq></Where></Query>

Simple, no? Well, not quite so simple. Try as you might, this query will never return just those items whose Title column is equal to "Yellow". Instead, the web service will happily ignore your fancy little CAML fragment and give you all the records in the list. Alas, no amount of cursing, head beating, keyboard throwing or foot stomping will make it otherwise. I assure you, I have tried all of those methods, and many more, to no avail. What DOES work is simply removing the <Query> and </Query> tags, like so:

<Where><Eq><FieldRef name="Title"><Value Type="Text">Yellow</Value></Eq></Where>

What's that you say? That's not how the SDK says it should be done? You spent hours searching the newsgroups and nobody once mentioned this little bit of CAML trickery? I feel your pain, my friend, believe me, I do. Were it not for my innate stubbornness and determination to beat SharePoint at it's own game, I would have given up on this vexing problem many moons ago. What can I tell you - CAML is a mysterious creature and we know not it's wild and wily ways. Now go ye forth and slay that noxious Query fiend - or at least stab at it until the next time it bites you on the rear!

Thursday, September 28, 2006

MOSS2007 Beta2TR Trials and Tribulations

Today was my lucky day to install a new MOSS2007 Beta2TR virtual machine from scratch. Oh, joy. Has anyone anywhere at any time so far managed to do this without uttering a single curse of frustration? I seriously doubt it. So here are the lessons I learned on today's adventure to MOSS-land:

  • If you plan on using a unique admin account (other than 'Administrator') for database access and application pools (such as 'SPSAdministrator') be sure that you are logged in as that account throughout the entire installation, upgrade and configuration process. Otherwise, you'll get all kinds of strange errors during installation and configuration. Oh, and don't forget to add that account to SQL before starting the process with full admin rights (or at least 'dbcreator' and 'securityadmin').
  • The slipstream process ain't all it's cracked up to be. I tried three times to slipstream the install, which worked through the installation process (assuming you sorted out the somewhat misleading upgrade instructions), but it failed to create the central admin application upon configuration all three times. What is not quite so obvious is that you need both MOSS and WSS TR's to do the update - just MOSS won't work. This is confusing as you don't need have to install WSS before MOSS the first time around. Just remember to a) copy all the files from the Beta 2 cd image into a local directory, then b) extract the update files for MOSS B2TR and WSS B2TR into that directory's \Update folder.
  • Central Administration will not work from a clean slipstream install (at least not for me it wouldn't and I was working from a fresh Win2k3 install). The configuration wizard runs and the central admin app is created but you can't access it - just an annoying 404 error every time. You must first install Beta 2, then run the configuration wizard (which creates the central admin app correctly) THEN run the WSS B2TR followed by the MOSS B2TR.

Finally, after much gnashing of teeth and flailing of limbs, I have a clean MOSS2007 image to work from. Now it's on to custom site definitions which, based on the install experience, promise to be a all-out man vs. machine war. Stay tuned for reports from the battlefield.

Wednesday, September 13, 2006

Business Portals vs. Line of Business Applications

A primary focus of our business is building custom SharePoint-based applications for our clients.  Naturally, being SharePoint gearheads, we believe that everything under the sun can somehow be made to work in SharePoint (and we're not often wrong) but we run into a great deal of confusion when presenting clients with various customization options.  One of the most difficult ideas to grasp is the separation between a business portal (BP) and a line of business application (LOB).  Which is which and where/how do you use each one?

To begin with, a business portal is defined as any application or set of applications (and the default SharePoint experience is really a set of integrated applications) that share a common brand or visual presentation and is usually delivered as a packaged installation (as opposed to a fixed location extranet or intranet) to customers, partners, or other constituents.  An LOB, on the other hand, is a distinct application that is deployed within an existing inter/intra/extranet implementation. 

On a more technical level, a customized set of WSS site definitions, web parts, and templates that together combine to form a branded collaboration application for, say, the real estate market, would be a business portal.  On the other hand, a set of web parts, lists, roll-ups, controls, or other programmatic elements, delivered individually or packaged together, and installed within an existing company intranet for tracking sales and orders, would be an line of business application. 

Just to muddy up the waters a bit, it should be pointed out that the two are not mutually exclusive - an LOB can be deployed within a business portal and a business portal can be created to serve internal as opposed to external customers (an IT help desk solution for a company with multiple, independent locations comes to mind).  Many organizations start creating LOB's soon after they deploy a new portal solution without realizing that's what they are doing, as they roll out custom web parts that roll-up, consolidate, or provide access to various sources of company data.

Business portals can be a very powerful tool for organizations that need to deliver rich web-enabled applications on a limited budget.  WSS provides a comprehensive, flexible, and customizable (and let's not forget FREE!) platform for creating dynamic web applications.  The best thing about BP's is that the framework is already in place - navigation, data storage (via lists), security, browser-based site management - so developers can focus on customizing and extending the framework without reinventing the wheel at every turn.  With the introduction of SharePoint 2007 and the improved customization options, along with built-in workflow and item-level security, forms-based authentication, and the business data catalog, expect a dramatic upsurge in the number of business portals being created, many of which will be offered as stand-alone applications (hint: expect to see several from us before the end of the year).