Facepalm of the Week: UnsecuredLayoutsPageBase

Someday, you may find yourself building a public-facing web site using SharePoint. Odds are pretty strong that when that day comes you are going to be creating at least one or two custom Application Pages which anonymous visitors must be able to access. You may already know that one way to achieve this is to have your custom page inherit from the aptly named UnsecuredLayoutsPageBase class.

What you may not know is that even when christened with a name like that, anonymous access for this type’s descendants doesn’t just work out of the box. If that were the case, I would have had a solid chunk of yesterday back to do the real work, we wouldn’t be having this little chat right now.

For some exotic purpose currently unbeknownst to this humble blogger, there are a pair of Boolean properties on this class that you have to override to always return true if you wish for the unwashed masses to gain an audience with your special page. They are AllowAnonymousAccess and AllowNullWeb:

protected override bool AllowAnonymousAccess
    get { return true; }
protected override bool AllowNullWeb 
    get { return true; } 

Provided you haven’t gummed up the works in some other obnoxiously subtle way, this little snippet should save the day for your pages that wish to service the unauthenticated.


It Makes One of These Out of U and I

While I was taking in a recent episode of Dot Net Rocks (the one covering the new LightSwitch rapid development platform), co-host Richard Campbell said something in passing that caught my ear. He described a hypothetical enterprise development scenario in which the “senior guys are building a set of WCF services that the, um, client-building guys can access”.

I batted an eye. Why are we assuming that our senior developers should be focused on the server side code?

This is no slight to Campbell, of course—he probably meant nothing by it at all, good-natured Canadian citizen that he is. But it called to mind tales I had heard before of concerns being separated across a team in this way. The more experienced members of the development staff get assigned the IMPORTANT BACK-END WORK, while they let the new kid, y’know, bring up some screens.

Sure, the nether-layers of your stack contain critical elements that must be tightly engineered for performance and accuracy. There is little value in a brilliantly laid-out page on a website that can’t perform, or in a screen that renders the wrong answers in a gorgeous typeface.

But is this really a working model for a team shipping successful software? Can we afford to regard an application’s User Experience as a foregone conclusion, or to pretend that the real art to be created is in the logic and plumbing of the application?

In the age of jQuery, WPF/Silverlight, and the iPad, our users are expecting a friendlier and more compelling experience from their software every day. Is the server really the place that a seasoned application developer can provide the most value? Would their skill and experience not be better put to use connecting meaningful information with the human being on the other side of the screen?

Not Registered as Safe, Indeed

The Perils of Renaming Your SharePoint 2010 Visual Web Part

The development experience for SharePoint 2010 is a huge step up from the elaborate Virtual Machine dance steps required by SharePoint 2007. Yet, as with any toolset this author has encountered, there remain a few hidden snares in the works.

One such snare presents itself when you have deployed a custom Visual Web Part created in Visual Studio 2010. All appears to be peachy as you move to add your new web part to a page on your site. Then, suddenly:

A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.

A quick Internet-based examination of the issue brings you to many a well-meaning post, generally aimed at SharePoint administrators, identifying the <SafeControls> section of the site’s web.config file as the scene of the crime. While this is technically true, there is no direct access to the destination site’s web.config file via a Visual Web Part project. As developers, we want this to be resolved in the code, not merely on the instance of deployment, lest we realize a slightly nauseating dystopian future where IT folk have to remember to update the config file every time your web part is deployed to a new environment.

You Missed A Spot

Thankfully, the problem is in your code. Well, not your code, per se, but rather the code generated by Visual Studio. Meticulous developer that you are, I’ll bet that you didn’t just leave the web part with its default moniker of VisualWebPart1. You right-clicked on it and gave it a meaningful name, so that the next code-smith to rummage through your work would speak of you with notes of awe quavering in their voice in some otherwise sleepy meeting yet to come.

Seriously, though, nice work. Meaningful names are an important aspect of great code. You simply did not go far enough in your nomenclatorial exploits. Each SharePoint Module generated in Visual Studio (including those that define Visual Web Parts) contains a hidden *.spdata file which enumerates (among other things) declarations of controls to be appended to the web.config’s safe list when the module is deployed. The problem indicated by our error du jour is that, while Visual Studio will automatically add a safe declaration for your custom web part in this file, it will not update the file when you rename the web part. So your SharePoint site is left saying “well, if I see this VisualWebPart1 dude, I’ll let him in, but Aptera.SharePoint.BrilliantlyNamedWebPart just isn’t on the list.”

As If You Aren’t Already Way Ahead of Me

You can remedy this (and any other renaming remnants) with a thorough search and replace of your code in Visual Studio. The relevant section of your web part’s spdata file should read:

    <SafeControl Name="SafeControlEntry1" Assembly="$SharePoint.Project.AssemblyFullName$" Namespace="Aptera.SharePoint.BrilliantlyNamedWebPart" TypeName="*" IsSafe="true" IsSafeAgainstScript="false" />