Wednesday, October 22, 2008

Thursday, September 18, 2008

SharePoint List Scalability

One-stop shopping for all things related to SharePoint list scalability and scalability in general.

Link saved for future use.

http://www.sharepointjoel.com/Lists/Posts/Post.aspx?ID=84

Wednesday, September 3, 2008

SearchBoxEx, FireFox and the Enter Key

Here's a problem with SearchBoxEx and FireFox that's easy to reproduce.

1) Create an out-of-the-box Publishing Portal. No customizations required.

2) With FireFox 2 or 3, go to the home page of the new site.

3) In the search box, enter a search phrase and press the enter key.

4) The home page simply refreshes instead of going to the search results page.

With IE 6/7 and Safari 3, everything works as expected. That is, the search results page is displayed.

I've reproduced this bug with three flavors of MOSS: MOSS RTM, with MOSS SP1 installed and finally with MOSS Infrastructure Update installed.

Looking at the traffic in Fiddler, it appears that *two* requests are being generated by FireFox. One to the search results page and one to the home page (in that order).

So...what's the fix?

After using http://www.rotary.com/ as inspiration, we came up with the following JavaScript that replaces the default key press event handler provided by MOSS.

To use the script, you'll need to supply the correct name of the submit method and input control id that is dynamically generated by SharePoint. After you do that, wrap the code in a script tag and place it on the page.

function replaceOnKeyPress()
{
var theFunction = "SDXXXXXXX_Submit();";
var theInputID = "ctl00_PlaceHolderSearchArea_SearchBox_SDXXXXXXX_InputKeywords";

var txt = document.getElementById(theInputID);
var browser=navigator.appName;

if (txt && (browser == "Netscape"))
{
txt.onkeypress = function(e)
{
var key = String.fromCharCode(e.keyCode);

if (key == "\n" key == "\r")
{
eval(theFunction);
return false;
}
}
}
}

replaceOnKeyPress();

Tuesday, July 22, 2008

Why Do My Form Fields Have A Yellow Background?

While this really doesn't have anything to do with SharePoint, both times I've been asked this question, it was in the context of somebody developing and testing a SharePoint list form.

The answer is that the form fields are yellow due to the Google Toolbar Autofill feature.

Monday, July 21, 2008

SharePoint EventID: 8tvn and 8nhi

Are you all of a sudden seeing zillions of messages in the event log with either event id 8tvn or 8nhi? The associated text reads something like:

Unable to retrieve parent node for item at: /SomeSite/SomeSubSite/Pages/Default.aspx of type: Area. This may be expected if changes have been made as the System Account, or if this is a POST request, request type: GET

or

Unable to retrieve parent node for item at: /SomeSite/Pages/SomePage.aspx of type: Page. This may be expected if changes have been made as the System Account, or if this is a POST request, request type: GET

Check and see if you've got more than 50 sites or pages underneath "SomeSite". If so, then you're probably bumping up against the default limit of 50 supported by the MOSS navigation infrastructure and you're getting errors when page/site number 51 and above is accessed. (At least that's what happening on the site I'm working on.)

To make the error go away, you probably need to bump up the value of "DynamicChildLimit" in the relevant NavSiteMapProviderdefinition in web.config. (Set it to zero if you don't want any limit.)

Alternatively, you can define additional NavSiteMapProviders (overriding the default value of "DynamicChildLimit") and reference them in your master page (or whatever is appropriate to your site).

Here are a couple of links to more information on MOSS navigation:

http://blogs.msdn.com/ecm/archive/2007/02/10/moss-navigation-deep-dive-part-1.aspx

http://www.sharepointblogs.com/spsherm/archive/2007/10/22/portalsitemapprovider-properties-includepages-dynamicchildlimit.aspx

Wednesday, July 2, 2008

CSS Reference Chart for SharePoint 2007 Update

Heather Solomon has updated her very handy SharePoint CSS reference chart.

This reference, along with SharePoint Skinner, was a life saver a few months back when I was working on a SharePoint rebranding project.

Indexing PDF Documents on SharePoint

Everything you need to know about installing the PDF iFilter on WSS and MOSS.

http://www.moss2007.be/blogs/vandest/archive/2007/09/19/sharepoint-2007-and-pdf-indexing.aspx

One little hint from the "once bitten, twice shy" department: if after installing this iFilter someone claims that a particular PDF document is still NOT being indexed, double-check to make sure that the document in question doesn't just simply contain a image scan with no text.

Tuesday, July 1, 2008

SharePoint Publishing: Enabling Page Settings and Schedule

Scenario: you have a SharePoint publishing site and the Page dropdown on the Page Editing Toolbar has a menuitem that says "Page Settings", not "Page Settings and Schedule". This is bad because you want to be able to schedule when a page will first appear and end.

How do you (re-)enable the "Page Settings and Schedule" choice?

Click the "Settings/Document Library Settings" menuitem for the Pages document library (http://SomeSite/Pages/Forms/AllItems.aspx).

1) In "versioning settings", ensure that content approval is turned on.

2) In "manage item scheduling", ensure that "enable scheduling of items in this list" is checked.

That should do it.

Update: after writing the above post, I found another post addressing the same issue. You can find it here.

Wednesday, June 25, 2008

SharePoint Designer Out of Sync?

Occasionally, SPD will get out-of-whack with reality. For example, it will report that a file is checked out when it's not. Or when you attempt to save a file, it will report that a newer file exists and fall into an endless loop of dialog boxes asking you what to do.

The fix is clearing out the local caches residing on your computer.

Here's a good explanation of how.

Monday, June 23, 2008

Using Formulas in Calculated Fields

Every three or four months, I have to use a formula in a calculated field. And every three or four months, I spend 5 minutes searching for some common examples because I've totally forgotten the syntax.

At least now I won't have to search far for the link.

http://office.microsoft.com/en-us/sharepointtechnology/HA011609471033.aspx

Thursday, June 12, 2008

Publishing Page Settings Broken By Missing User ID

I recently tripped across an issue with MOSS publishing that caused considerable head scratching. Because the scenario that gave rise to this is (probably) quite rare, I doubt many people will encounter this in “real life”. So with that in mind, here’s what happened.

My current assignment is on a project where the previous consultants were let go. When the previous firm left, the only deliverable they gave to my client was a content database detached from the consultant’s MOSS development environment. No features. No solutions. Just a database.

This method of delivery had the unfortunate downside of leaving occasional “loose ends” in the database such as broken page layout links and references to user ids that don’t exist in the client’s environment.

Now the problem of broken page layout links arising in certain circumstances is well-known. Someone has even written a STSADM extension to deal with the problem: (http://stsadm.blogspot.com/2007_08_01_archive.html)

However, the user ids that no longer exist in the target environment can cause considerable consternation if they are removed from the MOSS “people and groups”. For example, if a “bogus” user id is deleted from the system, you’ll no longer be able to view the “page settings” for each publishing page that was originally created by the now deleted user id. (The MOSS stack trace clearly indicates that it’s looking for the now missing user id.) As far as I know, there is no “easy code fix” like there is for broken page layout URLs because the “created by” field associated with each page appears to be read only.

So, what to do about it? The only solution I found was to follow the following steps:

-- create a new page

-- copy the content in the various page layout fields from the old “broken” page to the new page

-- save the new page

-- delete the old

-- rename the new page to use the old name.

All this can be done via the browser (no need for SharePoint Designer). The process could also be automated with C#, but given the low number of “legacy” pages that we had, we just decided to stick with the manual process.

Thursday, June 5, 2008

Recursion in Business Programs

Lately I've been listening to the podcasts at stackoverflow and have been really enjoying them. But, I chuckled a bit while listening to podcast #3. During that episode they get into a discussion of Computer Science vs. Software Engineering and it's during that discussion that Jeff and Joel come to the consensus that outside of systems-level programs like (for example) writing a compiler, recursion is basically useless in garden-variety business apps.

I laughed because just that day I had written a recursive method to traverse a tree containing pages of a medical encylopedia in order to import the pages into an equivalent tree of SharePoint publishing sites. I mean, you don't get much more "business-y" than SharePoint!

So while I agree that recursion is a rare bird in business apps, it does come in handy every now and then.

Saturday, May 24, 2008

SharePoint Database Connection Timeout

So, I'm writing this program that imports content of a medical encyclopedia into a SharePoint publishing site. The content is delivered in the form of about 1500 XML files with each file representing a page in the encyclopedia. Data in each XML file describes how each page is linked the overall structure. (For the most part, it's a tree. Though a few pages have more than one parent.)

Anyway, while the import program works fine, I noticed while running it inside of my very overworked virtual machine, SQL Server periodically goes to "out to lunch" and pegs the CPU to 100% for a few minutes. I guess it's reorg-ing something or another. During that time, the SharePoint API will occasionally throw a "can't connect to the database" exception. Apparently the 45 second default value for timing out connection attempts to the SharePoint database is insufficient. Ouch.

Fortunately, bumping up the timeout value is easy with stsadm. Just invoke the following command to bump it up to (for example) 3 minutes.

stsadm -o setproperty -pn database-connection-timeout -pv 180

Thursday, May 22, 2008

Add Images To SharePoint Publishing Site

Use the C# and the SharePoint API to add images to a publishing site.

using (SPSite siteCollection = new SPSite("http://SomeSiteCollection"))
{
using (SPWeb site = siteCollection.AllWebs["/SomeSite"])
{
SPDocumentLibrary doclib = (SPDocumentLibrary) site.Lists["Images"];

string filename = @"SomeImage.jpg";
string fileDir = @"c:\SomeImageDir";
string doclibRelPath = doclib.RootFolder.ServerRelativeUrl;
string doclibPath = siteCollection.MakeFullUrl(doclibRelPath);
string docPath = doclibPath + '\\' + filename;

Stream documentStream = new FileStream(fileDir + '\\' + filename, FileMode.Open);

SPFile file = site.Files.Add(docPath, documentStream);
file.CheckIn(string.Empty);
file.Publish(string.Empty);
file.Approve(string.Empty);

documentStream.Close();
}
}

Dispose Or Not To Dispose?

The good news is that SharePoint has a full-featured API layer that opens up access to...just about everything within the system.

The bad news is that the API can be a challenge at times due to things like naming inconsistencies between it and the user interface (e.g. SPSite really means "site collection" or instead of PublishingWeb.WelcomePage it's PublishingWeb.DefaultPage) and simply the fact that the surface layer of the API is BIG.

One of the hardest things to get right is figuring out when to call Dispose() on objects returned by the API. If you neglect to invoke Dispose() when needed, serious memory leaks will occur. On the other hand, calling Dispose() when you're not supposed to may (in the words of the Microsoft documentation) "cause the SharePoint object model to behave unpredictably or fail".

How exciting.

Now, there are a large number of blog posts, magazine articles, books, etc out there that help you figure out this Dispose() puzzle. But, this relatively new article article by Roger Lamb is the best that I've seen. It covers not only the "normal" patterns but also some pretty tricky edge cases as well. As a bonus, it also addresses not just core WSS functionality but also other namespaces (e.g. publishing) as well.

Wednesday, May 21, 2008

Exclude SharePoint Folders From Antivirus Scanning

This new knowledge base article caught my eye:

http://support.microsoft.com/kb/952167

MOSS Limits

How many sites can I create? How many documents can SharePoint hold? How many items can I insert into a list?

All this and many more are answered here: http://technet.microsoft.com/en-us/library/cc262787.aspx

SharePoint Webcasts, Podcasts and Labs

This should keep you busy for a long time...

http://www.microsoft.com/events/series/sharepointserver.aspx?tab=overview

Wednesday, May 14, 2008

Accessing SharePoint Publishing Pages With The Object Model

Here's a quick and dirty code sample that "visits" each page in every publishing site within a SharePoint site collection.

In this case, "visiting" consists of writing the check-out and approval status of each page to the console and (if necessary) ensuring that the page is checked-in and approved.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;

namespace MyUtilities
{
class Program
{
static void Main(string[] args)
{
const string indent = " ";

using (SPSite site = new SPSite("http://SomeSite"))
{
SPWebCollection webs = site.AllWebs;

foreach (SPWeb web in webs)
{
// only look at publishing sites
if (!PublishingWeb.IsPublishingWeb(web))
{
continue;
}

PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);

Console.WriteLine("Site: {0}", pubWeb.Title);

PublishingPageCollection pages = pubWeb.GetPublishingPages();
foreach (PublishingPage page in pages)
{
SPModerationInformation mi = page.ListItem.ModerationInformation;

Console.WriteLine("{0}{1}: Check-out status-{2} Approval status-{3}.",
indent, page.Title,
page.ListItem.File.CheckOutStatus, mi.Status);

try
{
if (page.ListItem.File.CheckOutStatus != SPFile.SPCheckOutStatus.None)
{
page.CheckIn("Automatically checked-in");
Console.WriteLine("{0}*** Checked-in", indent);
}
}
catch (Exception e)
{
Console.WriteLine("{0}Unable to check-in page {1}. Exception: {2}",
indent, page.Title, e.Message);
}

try
{
if (mi.Status != SPModerationStatusType.Approved)
{
page.ListItem.File.Approve("Automatically approved.");
Console.WriteLine("{0}*** Approved", indent);
}
}
catch (Exception e)
{
Console.WriteLine("{0}Unable to approve page {1}. Exception: {2}",
indent, page.Title, e.Message);
}
}
}
}
}
}
}


WSS SDK Object Model Programming Samples

I'm constantly pointing people to these very simple, but helpful SharePoint object model code samples found in the WSS SDK. Problem is, it always takes me a few minutes to locate them. Not anymore...

http://msdn.microsoft.com/en-us/library/ms412748.aspx

Speaking of helpful samples, here's a link to some code that illustrates the following common techniques:
  • getting a reference to a site
  • iterating over all lists in a site
  • getting a reference to a list
  • getting a reference to an item in a list
  • getting a reference to the item's properties
  • getting a reference to a document and its properties
  • adding a new item to a listmodifying an item in a list
http://www.sharepoint-tips.com/2006/08/common-and-simple-coding-tasks-in.html

Tuesday, May 13, 2008

SharePoint Publishing Site Style Sheets

Doug Ware has written a clear and straight-to-the-point explanation of how style sheets render in a SharePoint publishing site.

http://www.elumenotion.com/Blog/Lists/Posts/Post.aspx?ID=48

Monday, May 5, 2008

Checking User Names With Control-K

I was probably the last person on the planet to find this out a few weeks ago, but did you know that within SharePoint, you can use control-k to validate the spelling of any names entered into "people" boxes (e.g. the "Users/Groups" box when adding users to the site)? This shortcut is equivalent to clicking the person-with-a-checkbox icon.

Thursday, April 24, 2008

SharePoint Explorer View Not Working?

Does the "Open with Windows Explorer" menu item not work on a document library?

Make sure that the "WebClient" service is started. By default, it's disabled in Windows 2003.

Wednesday, April 16, 2008

Passing Arguments to Silverlight Web Parts

Here's how you can pass values to Silverlight applications embedded inside of a (SharePoint) web part.

As an example, consider the HelloSilverlight example from the recently posted Silverlight for SharePoint Blueprints. We want to allow users configuring the web part to specifiy who is being greeted.

STEP ONE:
Create a browsable public property inside of the HelloSilverlight2 web part (HelloSilverlight2.cs).

private string name = "Gaylord"; // default value


[Personalizable(PersonalizationScope.Shared),
WebBrowsable(true),
WebDisplayName("Name"),
WebDescription("The person who is being greeted."),
Category("Configuration")]
public string Name
{
get { return name; }
set { name = value; }
}


STEP TWO:
Set the InitParameters property of your instance of
System.Web.UI.SilverlightControls.Silverlight. Specifically, add the following line of code to HelloSilverlight2.CreateChildControls().

silverlightControl.InitParameters =
string.Format("Name={0}", Name);

Note: if you have multiple parameter to pass, separate each key/value pair with a comma.

STEP THREE:
Go now to method Application_Startup() of your Silverlight application (App.xaml.cs). Extract the Name parameter from the StartupEventArgs instance passed as an argument to Application_Startup().

string name = e.InitParams["Name"];

STEP FOUR:
For the HelloSilverlight2 app, we want to pass in the value for Name to the instance of Page. Therefore, we'll create a new contructor for Page

private string name;
private string displayText;

public Page(string name)
{
InitializeComponent();
this.name = name;
displayText = string.Format("Hello {0}!", name);
HelloWorldTextBlock.Text = displayText;
}


and invoke the new constructor (instead of the old parameterless constructor) inside of Application_Startup().

this.RootVisual = new Page(name);

For completeness sake, you'll want to modify TextBlock_MouseLeftButtonUp() to use the value of displayText.

Tuesday, April 15, 2008

SharePoint New Icon

For the ump-teenth time, I've been asked "how long does the new graphic persist on a new document or list item"?

Well, according to this guy the answers are:


"How long does the New! icon display after I add an item?" and "How do I prevent the New! icon from displaying?"


The New! icon displays for 2 days by default, but you can use the command line to set that:
[SharePoint Bin Directory]\stsadm.exe -o setproperty -propertyname days-to-show-new-icon -propertyvalue [Days to Display] -url [Your Virtual Server's URL]


To hide the New! icon, set [Days to Display] to 0. An alternate and unsupported approach is to replace the New! icon with a clear gif file.


The only problem with this answer is that it always takes me 10 minutes of searching to find it. But, I just fixed that problem by posting here... :-)

Silverlight SharePoint BluePrint Samples Not Working?

Having trouble getting the new Silverlight and SharePoint examples working? Turns out that you're not alone.

Help is available here and here.

In a nutshell, you need to fix some typos in various scripts, make sure the necessary runtimes are installed, update web.config and (whew!) add a new MIME type to IIS.

Saturday, April 12, 2008

One Year Later...

And this blog is still here. Crazy...