So, this is the weirdest bug I’ve seen in quite some time. I’d inherited some code, which includes a settings page in the _layouts directory. It’s a pretty normal page – nothing particularly bad about it, and it seemed to work nicely. Then I received a call about an error with it:
Now, here is the weird thing. When I started to examine it, I tried to replicate the problem. And I realised that the page worked when I accessed it from the server, but threw an ArgumentNullException when I accessed it from a client.
Yes, you read that right. What machine you browsed to the page on mattered. The browsers were the same. The code worked when viewed on the server, and failed when viewed from the client. When I eventually fixed it, I swapped between the broken and fixed code a few times to prove it – this really was the behaviour!
I can only hope there is another factor I’ve not considered, ‘cos I don’t get how that can be the case.
The error message was:
Value cannot be null.
Parameter name: serverContext at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(ServerContext serverContext, Boolean IgnoreUserPrivacy, Boolean backwardCompatible)
at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(ServerContext serverContext)
at MyAssembly.Pages.SettingsPage.OnLoad(EventArgs e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Looking in my code, I only had one call to the UserProfileManager constructor:
UserProfileManager oMgr = new UserProfileManager(ServerContext.Current);
ServerContext is in a SharePoint assembly, so it was out with reflector:
Ok, so we’re just calling GetContext() with the HttpContext. What goes on in there? This mess…
Yes, it’s nice and easy to figure out the logic of what’s going on in there. The short of it is that I saw several ways of NULL being returned – which would then cause our error.
So, my solution? Well, I didn’t like that mess, so I tried a different GetContext() method.
UserProfileManager oMgr = new UserProfileManager(ServerContext.GetContext(this.Site));
This worked when browsed to on either client or server. I chose that overload as it is much simpler, and doesn’t seem to rely at all on the HttpContext at all
I still don’t get how it can be different between the client and server, though. Post your ideas here!
To check, I reverted my code back to it’s original form – and the exception reappeared. I then added another AAM:
The Extranet one is what I added – and suddenly the error went away – and my code worked. Interesting.