Will "the Mighty" Strohl

Steps to Convert a WSP DotNetNuke Module to WAP

First of all, if you’re asking, “What is that,” let me elaborate.  A WSP module is also known as a “Web Site Project” module.  Basically, what this means is that the module does not need to be precompiled into an assembly (DLL) to run.  It pre-compiles as your web site responds to its first web request.  Alternatively, you can also build your DotNetNuke® modules using the WAP, or “Web Application Project” method.  This method will compile your code behind into one or more neat little assemblies, effectively hiding your source code from anyone that has direct access to the file system of your module and/or website.

I am not going to going any great detail of why you’d want to prefer one method over the other – especially since in some cases, these points may not apply.  In short, myself and many others prefer the WAP method of building a module for one or more of the following reasons:

  • Hide source code
  • Protect the module from direct changes
  • Easier inclusion into a source control system
  • More controlled module developer environment
  • Sandboxed staging and/or development cycles
  • Better performance when your website first compiles
  • And more…

While you can develop and package your modules as a WSP solution, your source code is free for everyone to see and modify.  In this instance, you’d definitely want to use the WAP method if you’re going to sell your modules commercially – even if those modules are still privately sold.

Most often, a module is easier to build from scratch using the WSP method though.  I know this is true for many people I know.  In fact, I know of a few people who always begin their module development using WSP, and then convert it later to a WAP module.  Development can be faster with a WSP module – especially when debugging.  However, at some point, you will likely be forced to step back and convert your WSP module to a WAP module.  (Though, in order to take this step, you cannot be using any Express Editions of Visual Studio.) 

Here’s the steps I take…

Converting the WSP Module to WAP

In the beginning, if you’ve done this on your own already, you have undoubtedly run into the problem where your WAP-converted solution will not regenerate the designer files required to allow your module to build and view on your development site.  That is the primary motivation of this post.  I have done this many more times than I’d like to admit, so I have found a path to take that forces your designer files to be auto-generated every single time, and not just when Visual Studio decides to do it. 

Please Note!!!  DO NOT build your solution at any point!  Wait until the steps tell you to!  Doing so, will not auto-generate the designer files.

Don’t worry about Visual Studio just yet.  Keep it closed for the time being.  Also, the first time you do this, it might take a while since you’re reading and following directions.  However, using these steps, I have been able to completely migrate a module to WAP in less than 30 minutes.  Though, the time really depends on the module.  The longest time I had was still less than an hour.  I converted an entire website’s 24 custom WSP modules to WAP in a week – and that’s including QA and everything – from start to roll-out.

In short, the steps are:

  1. Make a New Folder for Your Module
  2. Move Your Existing Module Files
  3. Copy Solution & Project Files
  4. Update the Solution & Project Files
  5. Create Designer File Place Holders
  6. Open Your Solution
  7. Update the User Control Mark-Up
  8. Resolve Any Errors
  9. Update the Project Properties
  10. Build the Solution
  11. Fix Web.Config
  12. Check Your Bin Folder
  13. Update the Module Definition
  14. View the Site

Make a New Folder for Your Module

In some cases, this may not be necessary, but it makes these steps super simple, so you might want to do this in a separate development instance of DNN.  You can merge your files back into your original development environment later.

In your DesktopModules directory, make a new folder with the appropriate name.  I prefer the folder naming scheme of [Company Name]/[Module Name].  Also, add a folder named “My Project” in the root of your module directory.

If your module is using a DataProvider pattern, create the following folder structure in the root of your module directory (the naming assumes you’re using an SQL DataProvider):

<module root>/Providers/DataProviders/SqlDataProvider/

Also add a “My Project” folder into your new SqlDataProvider folder.  In the end, your folder structure should look something like this:

Folder Structure

Move Your Existing Module Files

In nearly all cases, you will need all of the files that are in your current WSP module directory, and in many cases, the WSP files in the App_Code directory too.  Save a copy of all of your WSP files in a zip file somewhere, and move the originals to the module folder you just created.  The saved files will allow you to roll back later, if necessary.  Delete the original module files.

If you have any files in the App_Code directory, put them into a subfolder of your new module directory.  I often use a folder named “Entities” for any database object classes, and then a “Components” folder for any controller or utility classes.  It keeps things and life simple – except in the case of very complicated modules.

If your module is using a DataProvider, you will need to copy those files in a different place, namely into your SqlDataProvider folder.  The files that should be there may include the SqlDataProvider scripts, and the SqlDataProvider.vb (concrete provider class).  Generally, there are not any other files here.

Copy Solution & Project Files

In order for your WAP module to function, you will need at least one project file, and in many cases a solution file as well.  If you have a DataProvider project, the solution file is required.  (It is my preference to always have a solution file it’ll save you many headaches later.)  These files tell Visual Studio how to open your WAP module, what files are in it, some build preferences, and more.  In addition, you will need an Assembly.vb file for each project.  In many cases, you will have two projects in your module, the root module project, and the DataProvider project.  Each will need a project file and assembly class.

The easiest way I find to add these is to copy them from another module’s source code.  Simply download the source code of an existing WAP module, open the archive, and then drop the appropriate files in the appropriate places of your own project.  Don’t worry, they will be fixed for your project soon.  (I find simpler modules, such as the DNN core Links module is a good module to copy from.) 

The solution files and project files should match the destination folders as in the module you’re copying from.  For example, the project file from the root of the source module will go into the root of your new WAP module.  The project file from the SqlDataProvider directory of the source module will go into your SqlDataProvider directory, and so on.

Update the Solution & Project Files

The files you just copied will do you no good until you edit them to resolve a few issues.  Namely, you will need to update the file for namespaces, file paths, and directories. 

Open the solution file in a text editor.  NotePad or Notepad++ work just fine for this purpose.  Update the project names and the project file names to be what you want them to be.  Right now, you will not necessarily have either.  For example, if you’re doing this for the Links module, you might have to make an update similar to the example below:

FROM:  Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "DotNetNuke.Modules.Links", "DotNetNuke.Modules.Links.vbproj", "{C9B9FC2D-2D76-4446-897C-BA9E7B68EB0E}"
TO:  Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "YourCompany.Modules.ModuleName", "YourCompany.Modules.ModuleName.vbproj", "{C9B9FC2D-2D76-4446-897C-BA9E7B68EB0E}"

Close the Solution file, and open the Project file(s) in the text editor.

You should already have a Namespace in use in your module.  Do a “Find and Replace” to replace the existing Namespace in the file with your own.  Pay special attention to double-check the AssemblyName, and the DocumentationFile nodes. 

Next. change the names of the user controls to match your own.  Don’t panic.  The only files you need to do this for are the ascx, aspx, and ashx files.  Basically, any files that has code behind.

Don’t worry about changing any of the other file names or paths, unless you really want to.  I only do that if the module is small.  Otherwise, I do it through the Visual Studio UI later.  It’s generally faster, and less error prone.

Near the bottom of the root project file, you will need to update the IISUrl and IISAppRootUrl nodes to reflect the correct URL and path of your new module.  This will not be necessary for your SqlDataProvider project.  If you see those nodes in this project, you copied the wrong project file into the SqlDataProvider file.

Create Designer File Place Holders

Your user controls (and pages if you have them) need to have designer files to allow Visual Studio to build your project, and also for your code behind to not have errors.  Also, it’d be nice to have intellisense.  :)  Create a blank class file for each of your user controls with the proper names.  For example, a user control named DefaultView.ascx should have a designer file named DefaultView.ascx.designer.vb

Now, add a snippet similar to the following to each of your designer files.  The class name should match the class name of your code behind and user control.

   1: Namespace YourCompany.Modules.ModuleName
   3:     Partial Public Class YourClassName
   5:     End Class
   7: End Namespace

Open Your Solution

It’s finally time to open your solution!  I know you’re excited at this point, but make sure that you still DO NOT build your module until you’re told.  If you do, this won’t work.

If you get an error about IIS, then your URL paths in the Project file were not properly updated.  Close Visual Studio and fix the IIS paths in the project file using your text editor.

When you open your solution file, you may be asked to upgrade your solution to a newer version of the .Net framework.  That’s fine, go ahead and do it.  In fact, you should, unless it’s for .Net 4.0.  You should hold off on that right now, unless your environment is already set-up for it.

You will probably have a few errors in your Error Window.  Go ahead and fix any that are in your code.  Leave the mark-up files alone for the moment. 

Now, close and reopen your solution file.

Update the User Control Mark-Up

This step is quite simple.  You have a directive in the top of each of your user control files.  There is an attribute that needs to be updated in order for Visual Studio and the ASP.Net worker process to correctly deal with your module.  Simply do a “Find and Replace” to change “CodeFile=” to “CodeBehind=” in those files.  Your change should look similar to the example below.

FROM:  <%@ Control Language="vb" Inherits="YourCompany.Modules.ModuleName.ViewName" CodeFile=”ViewName.ascx.vb" AutoEventWireup="false" Explicit="True" %>
TO:  <%@ Control Language="vb" Inherits="YourCompany.Modules.ModuleName.ViewName" CodeBehind=”ViewName.ascx.vb" AutoEventWireup="false" Explicit="True" %>

Resolve Any Errors

Finally, resolve any remaining errors in your project.  This includes any of the mark-up, code behind, and class files.  Some of the common things you might have to update are:

  • Fixing namespaces
  • Importing project/assembly references
  • Removing any unnecessary project/assembly references
  • Importing namespaces
  • Removing cross-module dependencies

This step is incredibly important!  Until this is done, your designer files will not be generated.  Make sure you get this step completely done before moving on to the next step.

Update the Project Properties

Go into your project properties and update the Assembly Information for your module.  You can find this in the Application section.  Click the Assembly Information button, and update any of the information that you need to.

Project Properties

Assembly Information

Build the Solution

The time has come!  You are now allowed to build your solution.  If you did the previous steps correctly, this should be completely uneventful.  Your build should be error free, and your designer files should be populated.  (In some cases, they might have gotten populated before this step.)

Fix Web.Config

In some cases, this will not be necessary, but you should still check the web.config file in the root of your website.  Find the codeSubDirectories node.  Look in the child nodes and see if your module has an entry there.  If it does, remove it.

Check Your Bin Folder

When you built the module earlier, it should have created one or more assemblies and placed them in your /Bin folder.  Look in that folder and see if they are there.  If you don’t see them, then you will have to update your project file to fix the output path.  You can do this via your text editor or in your project properties.  Right-click on your project name, and choose “Properties” in the resulting context menu. 

Once you fix the build path, rebuilding the solution should put the assemblies in the right place.  However, you should also do a little clean-up at this point and remove the assemblies from anywhere that it created a Bin folder for you.

View the Site

Now comes the moment of truth…  With one exception, this should go well for you though.  You should be able to navigate to your development site’s URL, and it should come up just fine.  Go to the page(s) where you module(s) can be found and make sure they all work. The exception is when you have changed the path of the module.  In these instances, you may have to go into the Module Definitions and update the control path for the user controls in your module.  Easy stuff!

The only thing left at this point would be to update the manifest files for any installation packages that you might have.  Otherwise, you’re done!  Congratulations!

blog comments powered by Disqus