How to Approximate Application_Start in SharePoint Like a Gentleman

Sometimes, you just need to start something.

application_start_in_sharepoint

In a typical ASP.NET application, if we need to start something when it cranks to life in IIS, we simply add some custom code to the trusty Application_Start handler in our Global.asax file:

public class OmgAwesomeApplication : System.Web.HttpApplication {
    protected void Application_Start() {
        // omg something awesome here
    }
}

In a SharePoint app, however1, there is no Global.asaxfile, and indeed no such trusty method. This is by design, of course–running custom code inside SharePoint means relinquishing some control, especially over shared territory like events in the HttpApplication‘s lifecycle.

Still. Sometimes, you just need to start something.

Good place to start, Init?

So how can we hook into the start of an application in a SharePoint context? Rather than waiting for a leg up from our Visual Studio project template, let’s use the old rusted side door in ASP.NET that takes us straight into the Application Start kitchen.

An HTTP Module is simply code that is configured to run in IIS in response to requests on the server. The IHttpModule interface provides one method named Init. On-label usage dictates that we use this method to subscribe to the given HttpApplication‘s BeginRequest and EndRequest events:

public void Init(HttpApplication application) {
    application.BeginRequest +=
        (new EventHandler(this.Application_BeginRequest));
    application.EndRequest +=
        (new EventHandler(this.Application_EndRequest));
}

Now clear your mind, and forget about subscribing to these events. For our purposes here, we just want to run some code one time (and one time only) when the HttpApplication starts up. And it just so happens that our Init function runs right when the HttpApplication starts up. So:

public abstract class ApplicationStartHandler : IHttpModule {
    protected abstract void OnStart();
    public void Init(HttpApplication application) {
        OnStart();
    }
    public void Dispose() { }
}

Notice that I’ve built this out as an abstract class. This is not just because I am a gentleman. It’s because I want to encapsulate the pattern of running our yet-to-be-written custom code in the Init function. It’s also because I want to name the pattern in a way that makes it readable and understandable. Plus? I’m fancy.

If you don’t already, you’re really going to appreciate this fanciness/gentlemanliness in a few minutes.

Pulling our socks up and moving on, let’s inherit ApplicationStartHandler, and override the OnStart method to do something interesting (like perhaps boot up a ServiceStack host):

public class ServiceStackStarter : ApplicationStartHandler {
    protected override void OnStart() {
        var host = new MyAwesomeAppHost();
        host.Init();
    }
}

One last step before our fanciness is ready for prime time: we must let IIS know that our module exists. We do this by registering it in the Web Application’s web.config file, under configuration/system.webServer/modules.

<add name="ServiceStackStarter" type="Fazzaro.Blog.ServiceStackStarter, Fazzaro.Blog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=544b79730baa4957" />

As you can see, this requires skill in the realm of obtaining the PublicKeyToken of your module’s assembly. Details on this yak-shavery can be found here.

And once that’s in? Cut, print. Golly, was that ever a piece of 1337 SharePoint hax0r cake2.

Um. Hey, why is the server room on fire?

Multithreading, Mutual Exclusion, and the Advantages of Having Been a Gentleman

Yeah. IIS is a web server. And when we inject code into its very guts like this, we have to account for the fact that multiple instances of said code are being run at any given time.

To pull off the fix for our original cavalier implementation, we must add a static flag and a mutex to the ApplicationStartHandler class, using them in combination to ensure that the OnStart method is run once (and only once):

public abstract class ApplicationStartHandler : IHttpModule { 

    private readonly static object _mutex = new object(); 
    private static bool _initialized = false; 

    protected abstract void OnStart(); 

    public void Init(HttpApplication application) { 
        if (!_initialized) 
            lock (_mutex) 
            if (!_initialized) 
                Application_Start(); 
    }

    private void Application_Start() { 
        _initialized = true; 
        OnStart(); 
    }

    public void Dispose() { } 
}

Our OnStart method will now indeed run once and only once when the HttpApplication starts up, with no Global.asax in sight. And because we were gentlemen about the whole abstracting thing, our consuming code (in this case, the ServiceStackStarter class above) need not change in response to this fix.

This isn’t the first time I’ve noted here that standing on the shoulders of giants sometimes means leaving one of your favorite tools down on the ground. The trick is to stop being so shy about asking the giant to hand you a screwdriver.


  1. I’ve really got to stop beginning all of my sentences like this.
  2. Mmm. 1337 SharePoint hax0r cake.

Getting a “Trying to use an SPWeb object that has been closed or disposed” Exception? It’s this line in your custom application.master page

So there I was, minding my own and pooting forth the little green rosettas on a branding solution for a publishing site, when I navigated over to the site collection’s Keyword Management page (/_layouts/listkeywords.aspx). Only, instead of visually pleasing Keyword Management functionality besetting my oculars, I encountered the following White Screen of Death:

error_thumb

 

Of course, it’s SharePoint Development 101 to have properly disposed of any SPSite or SPWeb objects we create. At the same time, we have to be careful not to toss out the current SPContext‘s reference to these same types, at the risk of seeing just such an error as above.

Luckily, this was just a branding project, and there were precious few lines of custom server-side code that could be culprit in this case. So, my joy would lie in sifting through a few .cs files for a wayward disposal of the current web object, right?

Yes, but joy wouldn’t have warranted a blog post. That’s how I know the SharePoint API really loves me.

CustomApplication.master v. Drawing Board

After a hardy scrubbing of the Internet floor for an answer to my dilemma, I found a single reference to this exact situation. Sadly, the solution given was less than specific:

 

Instead of taking a copy of default.master, try taking a copy of application.master and modify that one.

So, re-build an entire master page?

The moral is that I should have done it this way from the beginning, but rework at this late hour would cause more boogers than it would un-cause. Instead, I took the tack of digging into the out-of-the-box copies of default.master and application.master, hunting for the very difference that would unleash our titular error.

Now, I could go on and on and on about the subtleties that set these two master page layouts apart, and that might be funny to someone standing over your watching you read this post, turning colors while you scan for the copy and paste bit.

But you’re here for the answer, and you’re clearly no fun at all, so, here. Take the following line out of your version of application.master, and our mystery error will take its ball and go home:

<WebPartPages:SPWebPartManager ID="m" runat="Server" />

You’ll forgive me if I leave it as an exercise to the abused reader to explain why this mysterious control would clearly violate SharePoint coding principals like, say, not disposing of the current SPWeb object.

I, for one, am going to go ahead and try to my afternoon back.

How I Convinced SharePoints 2007 And 2010 To Play Nice On The Same Team Build Server

I broke the build this week. Without touching any code, for a project I wasn’t even working on.

SharePoint 2010 is still packing on its freshman fifteen. It’s a fair assumption that even if you are rocking this newer version of the collaboration platform, there is still plenty of MOSS 2007 / WSS 3.0 work being done within earshot. Add a shared resource like Team Foundation Server to the mix, and things can start to get interesting for the portal development team.

So there I was, well on my way to achieving automated check-in build goodness for my current SharePoint 2010 project. The good folks at MSDN have supplied instructions for just such an occasion, and I followed them to the proverbial T, availing the necessary version 14 assemblies to our TFS-sanctioned build machine. Shortly thereafter, my shiny new build was running green, and the hills were alive with the sound of continuous integration. Then, a knock at the entrance of my cubicle.

“Jon, do you know anything about this ‘SharePoint 2010 Reference Assemblies’ folder on the build server?”

Yes. Yes I did.

My colleague politely went on to explain that the build for their MOSS 2007 site had suddenly and mysteriously begun to break that afternoon. In reply, I donned the hair shirt and dug in to find a fix. Soon, I had arrived at a simple enough patch for this little inter-version SharePoint awkwardness, and I brought it here to share with you today.

The Key Is The Key

The most lightweight of all the changes recommended in the MSDN article was the addition of a single Registry key to the build server, indicating the location of the aforementioned SharePoint reference assemblies folder. I found that once this key was removed, the MOSS team’s build woes had dissolved, and mine had returned.

With no other build server available, the simplest solution was to add or remove the key from the server’s Registry at the start of each build, using a pair of .reg files and a command line call to regedit from within each build script.

This is the file used to add the key, for SharePoint 2010 builds:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\SharePoint14]@]
@="C:\\Program Files\\Reference Assemblies\\SharePoint"

And here, for SharePoint 2007 efforts, is the corresponding one used to remove the key:

Windows Registry Editor Version 5.00
[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\SharePoint14]@]

Once those files have been created, you can add them directly to the appropriate solution by right-clicking on the Solution node in Visual Studio’s Solution Explorer pane, and selecting Add > Existing Item.

sp2007reg_thumb_2

sp2010reg_thumb_1

Assuming that your projects already have Team Builds configured, add a BeforeCompile Target to the TFSBuild.proj file in each, using the Exec task to merge the appropriate .reg file with a call to regedit /s, like this:

  <Target Name="BeforeCompile">
    <PropertyGroup>
      <RegFile>$(SolutionDir)\pre-build.reg</RegFile>
    </PropertyGroup>
    
    <!-- Merge the pre-build .reg file -->
    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="Preparing Build Server">
      <Output TaskParameter="Id" PropertyName="StepId" />
    </BuildStep>
    <Exec Command="regedit /s &quot;$(RegFile)&quot;" />
    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Succeeded" />
  </Target>

Now SharePoint 2007 and 2010 are building together, in perfect harmony. Just like in that Eddie Murphy /Joe Piscopo song.

Oh, All Right

Okay, it’s not perfect harmony. Should the builds coincide, one of them will fail, depending on who wrote to the registry last.

Nevertheless, there is something to be said for good enough. Especially when there are more important and less nerdy things to tighten down than the continuity and integrity of your continuous integration.

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.

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:

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

Thank You For Sharing

Automated Deployment for SharePoint 2007 with Team Server and VSeWSS

So you’ve built a custom Web Part. VSeWSS has been your tool of choice, especially since you lassoed that pkg folder into source control. It deftly dispatches the drudgery of creating WSP and XML files from your content and code. It even writes you an adorable little batch file to provide a smooth install with just a double-click. But you and I both know that’s not enough. It’s the twenty-first flippin’ century, and we want Continuous Integration.

I’m going to go ahead and assume that you have checked your VSeWSS project into Team Foundation Server, and created a basic Team Build that is kicked off on a check-in. If you haven’t, by all means, go set that up. The rest of the class and I are waiting.

Ps I Love You

The SharePoint administration command-line tool stsadm is designed in such a way that it only operates on the SharePoint server instance on the local machine. This is all fine and dandy for the small shop whose Team and SharePoint Servers (as well as their Exchange, SQL, and warez servers) reside on the same put-upon little machine. For the rest of us, however, this means that we have to bribe a lonely sysadmin to log on to the SharePoint box and copy/execute the aforementioned batch file. Or, we could whisper a prayer and have it answered by a miraculous man known only as Mark Russinovich.

Several years back, Mr. Russinovich decided that it was about time we had a decent tool to run commands on a remote Windows machine. He was right, and today we have PsExec. Step one, for us, is to download and install PsTools on our Team Server host.

If You MSBuild It…

Step two is slightly more developer-intensive. And by developer-intensive, I of course mean that you will have to copy and paste the MSBuild code from this post into your TFSBuild.proj file, pausing only briefly to modify some configuratory values on your way to SharePointy continuously integrational bliss. You probably will not need to alter the Executables values from the listing below except for the psexec credentials, but surely you must have a better name for your SharePoint solution.

<!--Figure the First, in which our constants are defined -->
<PropertyGroup>

  <!--Executables-->
  <Devenv>"%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\devenv"</Devenv>
  <Psexec>psexec /i /accepteula \\$(TargetServer) /u spAdminUsername /p s01337itHz</Psexec>

  <!--Paths-->
  <SolutionDir>$(SourceDir)\BestPortalEver</SolutionDir>
  <ProjectDir>$(SolutionDir)\MahWebParts</ProjectDir>
  <TempDropFolder>%TEMP%\$(BuildNumber)</TempDropFolder>

  <!--Etc.-->
  <Configuration>Release</Configuration>
  <SolutionFileName>BestPortalEver.sln</SolutionFileName>
  <WSPName>Aptera.Blog.BestPortalEver.MahWebParts.wsp</WSPName>
  <TargetServer>development.sharepoint.apterasoftware.com</TargetServer>

</PropertyGroup>

The third step is to add an AfterCompile Target, in which we will spin up a second instance of Visual Studio to build the solution with the /Package switch. This will (oddly enough) fill out the pkg folder with the WSP and setup.bat files needed to deploy our solution.

<!--Figure the Second, in which we do it again the right way.-->
<Target Name="AfterCompile">
    
    <!-- Build using /package switch  -->
    <Exec Command="$(Devenv) "$(SolutionDir)\$(SolutionFileName)" /Deploy $(Configuration) /Package" />
    
    <!--Copy Package to the Drop Location-->
    <Exec Command="xcopy /y /e /i "$(ProjectDir)\bin\$(Configuration)\*.*" "$(DropLocation)\$(BuildNumber)\$(Configuration)\"" />

</Target>

This seems simple and straightforward enough; but keep your tin foil hat on, this is pre-2010 SharePoint development. The oddity here is that the pkg folder (being, from Team Server’s point of view, more source code than resultant binary files) defaults to Read-Only in the workspace. If you would be so bold as to launch your build at this point, it would trip on this step and fail with the following edifying pronouncement:

------ Validate solution and resolve deployment conflict(s) ------
Validating solution ...
EXEC : error : System.UnauthorizedAccessException
    Access to the path 'C:\Documents and Settings\tfsBuildUser\Local Settings\Temp\Aptera.Blog.BestPortalEver\Check-in Build\Sources\Aptera.Blog.BestPortalEver\MahWebParts\pkg\solution.xml' is denied.

The fix for this flounder is to remove the Read-Only flag from our favorite little output directory, just before the call to devenv:

<!-- Make the pkg folder and its contents writable -->
<Exec Command="attrib -R "$(ProjectDir)\pkg\*.*" /S /D" />

What Can PsExec Do For You

Now that we have a viable pkg folder full of deliverable SharePoint goodness, it is time to deliver the goods. To do this, we must call upon PsExec. Remember PsExec?

Back in step two, to simplify things, we added a property that sets up a call to PsExec with all of the necessary parameters, such as remote host name, user credentials, etc. Let’s see those again in slow-motion, for the people in the back:

<Psexec>psexec /i /accepteula \\$(TargetServer) /u mahSPAdminUser /p s01337itHz</Psexec>

Our fourth and final step is to create another Target named AfterDropBuild. In it we will use PsExec to copy the build’s outputs over to our SharePoint host, and execute the setup script:

<!--Figure the Third, in which the magic happens.-->
<Target Name="AfterDropBuild">
    
    <!--Copy Files to Target Server-->
    <Exec Command="$(Psexec) xcopy /y /e "$(DropLocation)\$(BuildNumber)\$(Configuration)\" "$(TempDropFolder)\"" />
    
    <!--Deactivate and Uninstall previous version of the Solution-->
    <Exec Command="$(Psexec) echo . | "$(TempDropFolder)\setup.bat" /uninstall " />
    
    <!--Install and Activate the Solution-->
    <Exec Command="$(Psexec) echo . | "$(TempDropFolder)\setup.bat" /install " />
    
</Target>

Thanks to John W Powell for providing the basis for this approach.

P.S. – A quick sidebar on calling VSeWSS’s setup.bat

Presumably under great duress and/or substance abuse, the decision was made on the VSeWSS team that when the generated setup script had finished its business, it would say so and wait more patiently than you for someone to hit the Enter key before it exited completely. This is highly convenient and even polite in the context of our lonely, lonely sysadmin running said batch file on our behalf, but it gets old pretty quickly when your Team Build is waiting just as patiently for the script to return control. Echoing a period and piping it into a script is a common technique for simulating the required keystroke at the script’s prompt.

In case that was keeping you up at night.

It’s A Pkg Deal

Persisting Custom SharePoint Feature Settings in a VSeWSS Project

The Visual Studio extensions for Windows SharePoint Services (VSeWSS) provide a pretty steady leg up to developers tasked with SharePoint 2007 customization. Not having to bake your own XML files from scratch or cram a custom deployment batch script into your post build step really gives one that peppy modern feeling. But for all the solid that the extensions do us, there are still one or two things I would change if it were up to me. One of these is how the pkg folder is handled.

Feature Configuration 101 (Or, Jump Back To This Part If You Didn’t Follow That At All)

When developing for SharePoint, the Feature is the key building block of your operation. The settings for each feature live, as one might guess, in its feature.xml file. A VSeWSS project automatically generates this file based on element manifests or Feature Receiver code it finds within. When the Package or Deploy commands are issued on the project, a folder named pkg is populated with these and other files necessary for deployment to a SharePoint site.

To that end, this pkg folder is treated much like the bin folder generated for most projects in Visual Studio–it is not automatically included in the project. This would be just ducky for a lone SharePoint developer shoving things straight out to a production site; but many of us work on teams with other developers. This usually involves trust falls, paintball outings, and source control.  While each of these can indeed involve a pkg in some way, the latter will be our raison d’être du jour.

Get On With It

As-is, the generated feature.xml file is enough to get you off the ground when deploying your custom SharePoint creation. However, there are many settings therein which may be necessary to alter manually; for example, to give your feature some professional polish like a title and description readable by humans and SharePoint administrators. The SharePoint Extension gods have therefore benevolently bestowed upon us the WSP View, for navigating and editing said files:

Editing feature.xml in the WSP View

It feels just like making real growed-up code changes.  The fine print on this is that your updates will be made locally, and they will be deployed properly to your local SharePoint site (presumably on your development virtual machine), but when you check in your project’s code for the other developers on your team to see, your alterations to anything in the pkg folder will not be included.

Fix it Already (Or, Skip To This Part If You’re Wearing a Bluetooth Headset and You’re Totally in a Hurry)

The solution to this is to simply include the pkg folder in the project, once it has been generated:

  1. Right-click your project, and select Package. This will create/update all of the necessary files and folders in pkg.
  2. With the project name highlighted in the Solution Explorer, click the Show All Files button.
  3. Right click on the pkg folder and select Include in Project.

Include in Project

Visual Studio will then treat these files as first class source, and control them by checking them in alongside your other files already enjoying this status. Once you have done this, the other devs on your team will finally be able to recognize your brilliance, and will probably stop dropping you or shooting you in unpleasant places during your other team-building activities.