Friday, June 20, 2008

Have a lot of SharePoint Users? Bring Cache

Bring Cache

Depending on your user base you may care very little about how caching works in SharePoint. But whether you plan on using it or not, you should at least know it's there and that it takes very little effort to turn it on.

Remember that almost everything in SharePoint resides in the content database. This coupled with the fact that opening a database connection is an extremely expensive operation means that there's potentially a lot more capacity to be had from a SharePoint site by simply enabling caching.

In my experience running the Microsoft Web Application Stress Tool on test SharePoint sites, most sites running caching profiles were able to achieve 33% more requests per second that those using no caching at all. That's a LOT more capacity to be had, and best of all it's free (you know...you've already paid a lot of money for MOSS).

To enable Page Output Caching you need to turn on both the Office SharePoint Server Publishing Infrastructure feature in the Site Collection and the Office SharePoint Server Publishing in the sub site. Disk Caching is turned on through the web.config.

Page Output Caching

Page Output Caching works a lot like ASP.NET page output caching, allowing you to cache pages in memory for a certain period of time and also maintain many cached versions of pages based off of Browser Type, Query String, HTTP Header, or some custom function that you write and implement in your pages. It's quite flexible.

You start off by defining Caching Profiles in Site Settings (that is, how you want to determined if something should be cached) and then assigning profiles to either of Authenticated or Anonymous users as they visit your site. For instance, you could choose to cache pages for anonymous users and not cache pages for authenticated users.

By default Cache Profiles inherit down to sub sites just like security, and like security you can change the inheritance at any sub site along the way.

Disk Caching

The other type of caching is Disk Caching which simply stores assets that you would normally fetch from the content database on disk. Disk Caching and Page Output Caching aren't mutually exclusive and actually marry quite well together. To enable disk output caching all you really need to do is open up the web.config for the site and change the BlobCache key to look like below:

<Blobcache location="C:\blobCache" path="\.(gif|jpg|png|css|js)$" maxSize="10" enabled="true" />

It's worth mentioning that path is a regular expressions of file types to cache to disk and maxSize is measured in gigabytes. The location is of course where these files will be persisted to disk.

Some Thoughts

I would strongly encourage you to enable caching schemes one or more of your SharePoint sites to try it out. Those that make the best candidates (stand to gain the most performance) are those that have a lot of users and have anonymous access turned on for the entire site collection (usually synonymous with public facing sites). If you think you're viewing a cached version of a page and you want to see the real content you can always suffix the query string with a nocache=1. IE. http://somedomain/Pages/default.aspx?nocache=1 displays the non cached version of default.aspx for the somedomain site.

So there it is. Enjoy your free performance gains. Like G.I. Joe says: "Knowing is half the battle."

Untitled

Happing Caching,
Tyler

Saturday, June 7, 2008

Free Microsoft E-Learning Vouchers Till June 30

Free E-Learning

I'm the kind of guy that does a couple certifications a year. Because of the tech stack I work in, most of these end up being Microsoft certifications. This year I ended up using the MS E-Learning for two SharePoint certifications (MCTS') and it wasn't half bad. Some of the material is a little cheesy and has a touch of marketing propaganda. It's also the kind of material you probably want to supplement with some MearsureUp or Transcender to ensure that you pass your exam the first time.

All that being said it covers the material in a efficient way and highlights a lot of the features of the product that you may not know about. The material could usually do with a little more depth, but it makes you aware enough to go do some research on your own if you want to go deeper. At the very least it helps you pose the right questions to go further your own learning.

The Sphiel

The below is from an MS E-Learning promo site:

Official Microsoft E-Learning provides you with a cost-effective, flexible, and easy way to build your skills on Microsoft technologies. Choose from more than 1,400 hours of training for IT professionals and developers on the latest products, including Windows Vista, Microsoft Office, Microsoft Office SharePoint Server, Windows Server, Microsoft SQL Server, and Microsoft Visual Studio. Microsoft also offers more than 200 hours of training for home and office users.

Developed by Microsoft technology experts, each course quickly provides you with the critical knowledge you need to excel at your job. Available online, 24 hours a day and seven days a week, the modular lesson format allows you to learn where you want and at your own pace. Take advantage of interactive online features that give you the flexibility to acquire new skills in the way that best suits your learning style.

For a limited time, you can try a free Official Microsoft E-Learning course!

Register to receive a promotional code that you can redeem for one free e-learning course.

Register for the free e-learning course offer

Offer details

This offer is limited to one individual Official Microsoft E-Learning course per person and does not apply to course collections, groups of courses, or any large legacy course that has 12 or more hours of training. The promotional code expires 30 days after you register. This offer expires on June 30, 2008.

So there you have it, a chance to save yourself (or your employer some money) if you were planning on doing some certs this summer. It's of note that the classes remain available for 18 months and only take about a week to go through so it may be worth signing up now and doing them later.

When I went through there were two promo codes, one for a free e-learning course and another which gave a 20% shopping cart discount.

So there it is, take it as you will.

Best,
Tyler

Wednesday, June 4, 2008

IIS 6 Host Headers on Win2k3 Yields 401.1

Haven't I met you before?

Sometimes it seems like there's so much random information you're supposed to keep in your head that it's a wonder any of it sticks. Keeping this blog has been surprisingly helpful, but things still seem to find their way through the cracks. To patch the holes I sometimes blog about the problem to increase my odds of remembering it. This is one such blog.

I was migrating a relatively plain ASP.NET site the other day, and after all of the assemblies and data had been migrated the last task was to set up a host header (something along the lines of http://somesite.somedomain.com).

After setting up the host header and setting a local IP mapping in a hosts file I was surprised to repeatedly get a 401.1 (Unauthorized: Access is denied due to invalid credentials).

Now of course there are MANY different scenarios that can yield a 401's, in fact while hunting for the answer I stumbled across this helpful article (again) that while didn't help my particular issue, I normally use to troubleshoot most 401s and 404s. As it turns out I've actually ran into this same problem before...twice. Hopefully I remember it this time. Anyway here's how it went down.

Symptoms

  1. You set a host header on a web site and are unable to access the machine by that host header without getting a 401.1 Access is denied due to invalid credentials.
  2. Your credentials are good and the App Pool is not running in the identity of an expired or invalid account.
  3. You can access that same site through a port number correctly.
  4. You are running Windows 2003.
  5. The web site is accessible via host header from other (remote) machines, just not locally.
  6. Also if you're debugging in Visual Studio you may get the error "Unable to start debugging on the web server. You do not have permissions to debug the server."

Treatment

This is actually all semi well documented in a Microsoft KB which never seems to surface when I go looking for it. All of this behavior has to do with a security check in the loop back adapter to prevent reflection attacks. Unfortunately there's no real cure. Like the KB suggests you can either disable loop back checks if this is a development machine or not security check for certain host headers that resolve back to the host.

Remembering my life, one blog entry at a time.

Best,
Tyler

Sunday, June 1, 2008

DataSource VS. DataSourceID (Internals)

An Old Question

I know .NET v3.5 has been around for a while now and that I should have all the v2.0 stuff down by now, but to be perfectly honest I don't. This was made extremely clear to me when a colleague asked me what the difference was between setting the DataSource and DataMember on a control vs. setting the DataSourceID. Maybe this post should have been made in 2005 (and it probably was by some other developer), but at the risk of reinventing an already aged wheel I'll go ahead and write this down for (at least) my own benefit.

We (this colleague and I) ended up getting into a discussion about Object/SQL DataSources and "new" .NET v2.0 controls like Grid/Form View, but then I got stumped on this one question. We were talking about how you don't need to explicitly call the DataBind() method when you assign DataSourceID but you do when you assign DataSource/DataMember. But that behavior begs the question:

"How do DataSourceID enabled controls know when to re/bind and when in the page life cycle do they call DataBind on themselves?"

An Old Answer

Since this is a two year old question I got pointed in the right direction by a blog post done by Manuel Abadia. I then turned to Reflector to validate what I read and make sense of everything.

DataSource and DataMember

You probably already know this one. Using these properties you explicitly set the DataSource and (potentially the DataMember). When you call DataBind() on the control it takes that bound data and uses it to go set a series of properties or build out a series of sub controls so that by the time Page Render comes around the control is all built out and ready to render out a bunch of markup driven by your datasource.

DataSourceID

When setting a DataSourceID a pretty similar behavior happens. The control takes note that the DataSourceID has changed and when PreRender comes around it calls DataBind() just like in .NET v1.x.

Here's some snippets from Reflector. The code below is from System.Web.UI.BaseDataBoundControl which .NET v2.0+ DataSourceID enabled controls inherit from.

public virtual string DataSourceID
{
    //omitted for brevity...
    set
    {
        if (string.IsNullOrEmpty(value) &&         !string.IsNullOrEmpty(this.DataSourceID))
        {
            this._requiresBindToNull = true;
        }
        this.ViewState["DataSourceID"] = value;
        this.OnDataPropertyChanged();
    }
}

Essentially the DataSourceID gets set in ViewState and then OnDataPropertyChanged gets fired (which really just sets a flag telling the control to call DataBind() when PreRender rolls around). Just in case you don't believe me the code is below (same class as before).

protected virtual void OnDataPropertyChanged()
{
    //omitted for brevity...
    if (this._inited)
    {
        this.RequiresDataBinding = true;
    }
}

Finally when PreRender comes around for the control we see pretty straight forward code telling the control to DataBind() if the _requiresDataBind flag as been set. The actual call to DataBind() happens in EnsureDataBound().

protected internal override void OnPreRender(EventArgs e)
{
    this._preRendered = true;
    this.EnsureDataBound();
    base.OnPreRender(e);
}
protected virtual void EnsureDataBound()
{
    try
    {
        this._throwOnDataPropertyChange = true;
        if (this.RequiresDataBinding &&
        ((this.DataSourceID.Length > 0) ||         this._requiresBindToNull))
        {
            this.DataBind();
            this._requiresBindToNull = false;
        }
    }
    finally
    {
        this._throwOnDataPropertyChange = false;
    }
}

So that's it. Not too bad really. The more I think about it the more I like it. It reminds me a lot of what it was like setting DataSources on WinForms controls, all that explicitly calling DataBind() goes away. Ideally it's one less thing to think about.

My Best,
Tyler