What happened to my SPContext?

This last iteration, we ran an interesting issue when services that we request through the SharePointServiceLocator depend on SPContext.Current. This seemed like a reasonable dependency assumption. We consume these services in feature receivers. They work fine when activating the feature via the SharePoint web UI, but don’t work when activating the feature via STSADM –o activatefeature command. Who knew SPContext isn’t available in this case? Not I. This is another example of the complexity of SharePoint development.

Luckily, if you’re on a SharePoint/WSS instance SPFarm.Local is always available, even if SPContext is not. We refactored the SharePointLogger, EventLogLogger and TraceLogger to ensure they don’t depend on SPContext. This forced us into an artificial restriction. We wanted the EventLogLogger to pull the name of the event source to write to from the current SPWebApplication’s property bag. In order to determine the current SPWebApplication we started with SPContext. We believe this to be the appropriate level to set the event source name since it is very likely that different web applications in the farm would like to use different event log event sources. The SharePointServiceLocator is also “safe” to use in feature receivers because its only external dependency is on a property bag setting on SPFarm.

I know that we can get to the SPWebApplication from the feature receiver’s SPFeatureReceiverProperties, but then we need to refactor services to sometimes get their context from SPContext and other times allow it to be passed in via property. Hopefully that service isn’t used before the necessary property is set. Messy… Let me know if anyone out there has a recommendation on how to solve this problem.

Comments (2)

  1. fcheung says:

    Thanks pstickne!

    You’re right. You can determine the SPSite, but that doesn’t help you if your code internally depends upon SPContext.Current. A solution could be to refactor your code that depends on SPContext.Current to instead use context that is pass in.