13991 Views // 0 Comments // Not Rated

Getting A User Control Targeting ASP.NET 3.5 Working In The SmartPart For SharePoint 2007

One of the really nice things about .NET 3.0 and .NET 3.5, in terms of upgrading existing .NET 2.0 applications, is that all three target the same (2.0) runtime. What this means for developers is that we only have to worry about referencing the correct assemblies. It's the same CLR, just with all the new goodies of WPF, WF, WCF, and LINQ.

I haven't gotten around to playing with Dynamic Data or MVC in ASP.NET 3.5, but a new "feature" I have plenty of experience with is AJAX. In ASP.NET 2.0, AJAX was an extension; it is now a first class citizen in ASP.NET 3.5. This means that there will be much less configuration issues to get all the beautiful client-side functionality working.

But what about SharePoint 2007? It is, by definition, an ASP.NET 2.0 web application. But since it targets the same runtime as ASP.NET 3.5, there's no technical reason why you can't have, for example, "3.5" user controls running on a "2.0" page. All the code gets complied down to the same CLR, so it should auto-magically work; we just have to get the assemblies right.

So what I'm going to do here is take you step-by-step (in terms of error messages) though upgrading your SharePoint 2007 web app from AJAX 2.0 to 3.5 on-the-fly, without needing to change any of your existing code. Take note my of usage of "web app" here. These are all web.config changes, so you don't have a make a server-wide SharePoint upgrade or anything like that; you can do it on an app-by-app basis to keep any regression issues in check.

I'm starting with a SharePoint 2007 Service Pack 1 web app that has the latest AJAX SmartPart installed, hosting a web user control that has update panels and AJAX Control Toolkit content which targets the 2.0 framework and was created with Visual Studio 2005. When we're done, everything will be rocking in 3.5!

Start by installing all the latest and greatest Visual Studio (2008) and .NET (3.5) applications and updates on your dev box. When this is done, open up the web project that contains your user control in VS 2008, and choose to upgrade your solution. This usually results in nothing more than a few harmless warnings.

Next, right click your project, and select "Properties." On the "Application" tab, select ".NET Framework 3.5" for the "Target Framework." Recompile your assembly. Finally, copy your control (both .ASCX and .CS/.VB files) to the "UserControls" folder under your web app on the server.

Launch your page, and we'll get the first error message from the SmartPart:

Cannot load file or assembly "System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35." The system cannot find the file specified.

Obviously, we need to install .NET 3.5 on the server. I said that getting 3.5 working will not require a server-wide change. I meant in terms of SharePoint. Installing .NET 3.5 has nothing to do with SharePoint; this is really more like an update of the computer itself. Download the latest from Microsoft's web site, and prepare for a reboot.

When the server comes back up, navigate back to your page. You'll be presented with a new error. The error itself may vary based on your actual control, but the resolution will be the same. Here's what I got:

The base class includes the field 'UpatePanel1', but its type (System.Web.UI.UpdatePanel) is not compatible with the type of control (System.Web.UI.UpdatePanel).

This reminds of me of the frightening reflection errors I used to get, when I'd see something like "...type 'X' cannot be converted to type 'X'..." and I'd have a heart attack. The problem here is that our control has a 3.5 version of the update panel, which the server now knows about, but the page is compiled in 2.0, and therefore can only resolve 2.0 update panels.

(I know it's actually 1.0.6.something; I'm going to use 2.0 heretofore to mean anything that targets the 2.0 framework, for simplicity sake.)

In order to get the control and page on the same page, (pun absolutely intended) we need to get both to talking to the 3.5 version of System.Web.Extensions. In SharePoint, we have no control over the page itself as an existential .ASPX file due to all the ghosting going on behind the scenes at the HTTP handler level. So what we need to do is get the entire web app using this exact assembly, so that pages and controls will all be on-the-fly compiled targeting the same framework version of it.

So I backedup the web.config file, opened it in notepad, and did a find-and-replace of "System.Web.Extensions, Version=1.0.61025.0" with "System.Web.Extensions, Version=" knowing that this is the assembly where the update panel lives. I saved it, which recycles the app pool, and loaded my page back up, feeling hopeful.

But now, instead of a nice little SmartPart error (as the last one was also), I got a nice big fat yellow and red ASP.NET error. As if having a broken control wasn't bad enough, I now had a broken page. Awesome. Here was the new problem:

The control with ID 'UpdatePanel1' requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it.

Barf. I had now regressed my life back to the point when I first threw an update panel on a page and called myself an AJAX developer, in much the same way a little girl puts on her mom's pearls and a pair of high heels and calls herself a movie star. I know that the standard problems that usually lead to errors like this (forgetting to put a script manager on the page, not having AJAX configured correctly in SharePoint, putting code in OnPreRender without calling it on the base class, programming drunk, etc.) couldn't be the case, because AJAX was working fine before my adventure into 3.5 world.

The previous step finally fixed the control (technically), inasmuch as it was now compiling happily in 3.5. What I think was happening was that as SharePoint assembled the page, we were still mixing 2.0 and 3.5. Although the user control was correctly referencing the 3.5 assembly, the script manager brought down from the ghosted master page was pre-complied in 2.0. Update panels and AJAX Control Toolkit controls need a script manager on page, and as is the case here, it has to be the right version; in other words, 3.5 update panels, for example, cannot register themselves with 2.0 script mangers.

The last step is do some binding redirection to make sure all content on the page that references this assembly is compiled using the correct framework version. Since the various versions of the .NET Framework can be installed side-by-side, different apps can target different runtimes. Luckily, Microsoft was very good about backwards compatibility here, so we can tell the web app to compile code targeting an older version of an assembly against a newer compiler, and it'll still work.

What we need to do is take the following markup:

Code Listing 1

  1. /><dependentAssembly>
  2. /><assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35">
  3. /><bindingRedirect oldVersion="" newVersion="">
  4. /></dependentAssembly>
  5. /><dependentAssembly>
  6. /><assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35">
  7. /><bindingRedirect oldVersion="" newVersion="">
  8. /></dependentAssembly>

And nestle it into the node under of the web.config for the web app. With this will do is force anything that references System.Web.Extensions 1.0 - 1.1 to be compiled with a reference to the 3.5 version. (Which is cool; VS 2008 will give you a warning if an assembly has a reference to another assembly from a higher version of the framework, but it'll work all the same.) You can see that Microsoft does this already in the web.config, redirecting anything that references WSS 2.0 to be compiled with WSS 3.0 instead.

And that does the trick! I experimented with skipping the find-and-replace step and just doing the binding redirection, but it didn't work, so I decided not to waste any more time. I might have just screwed something up in that experiment, so feel free to try and skip the find-and-replace; I'd be curious if you can get it to work.

So in recapitulation, all you have to do it compile your control in 3.5, install 3.5 on the server, and make sure anything it references in the web.config is also in 3.5 to get your 2.0 user controls to take advantage of 3.5. This should do it for me, AJAX, and SharePoint, since it's now time to tackle Silverlight!

No Tags

No Files

No Thoughts

Your Thoughts?

You need to login with Twitter to share a Thought on this post.