We always assumed wherever you have an HTTP Context (i.e., wherever SPContext.Current is not null), that you could access the SharePoint context through SPContext.Current. This was the case with MOSS 2007 RTM and SP1, but this changed with the recent Infrastructure Update. The following update to when SPContext is supported has been confirmed by Microsoft PSS. (Props to Nishand for confirming this behavior change.)
Prior to the IHttpHandler.ProcessRequest method, the SharePoint application runtime is busy building an impersonation context of the calling user. This means that you CANNOT access SPContext.Current UNTIL the ProcessRequest method. This also means within the constructor of the handler OR from a factory pattern– regardless of whether it’s a Page or IHttpHandler endpoint. Note that this is a COMPLETE CHANGE OF BEHAVIOR (processing timeline) that the infrastructure update introduces.
Bottom line– this means that if you are implementing IHttpHandlerFactory instances, you cannot access the SPContext.Current object or anything deriving from there in the factory—you must wait until IHttpHandler.ProcessRequest. (NOTE: I haven’t tested this, but this also will affect HTTP modules).
The following code sample demonstrates the bug. The handler factory will fail every time, while the handler will work every time.
using System.Web;
using Microsoft.SharePoint;
namespace NGSupport{
// Unsupported code: fails AFTER infrastructure update
public class TestHandlerFactory : IHttpHandlerFactory{
public IHttpHandler GetHandler(HttpContext context,
string requestType, string url, string pathTranslated) {
// Breaks every time (after infrastructure update)
// as WSS hasn’t loaded the impersonation context,
// and the SharePoint context is NOT available
var spContext = SPContext.Current;
return new TestHandler();
}
public void ReleaseHandler(IHttpHandler handler) {}
}
// Supported code: works every time
public class TestHandler : IHttpHandler{
public bool IsReusable{get { return true; } }
public void ProcessRequest(HttpContext context) {
// Will work just fine– you can always access SPContext.Current in ProcessRequest
var spContext = SPContext.Current;
context.Response.Write(spContext.Web.Title.ToString());
}
}
}
To test this out, compile this into a DLL called "NGSupport" and register the following handlers in web.config (may require elevated or WSS_Medium trust):
<add verb="GET,HEAD" path="foo.test" type="NGSupport.TestHandlerFactory, NGSupport" validate="false" />
<add verb="GET,HEAD" path="bar.test" type="NGSupport.TestHandler, NGSupport" validate="false" />
You should see that foo.test will work before the infrastructure update but break after it’s applied, however you’ll see that bar.test will always work as that is the supported code path.
Props to the NewsGator dev, support and qa teams for identifying and resolving this issue quickly.