|
 |
| DotNetNuke PA using ASP.NET 2.0 Coding Techniques
|
|
|
|
 |
|
 |
I've provided modifications to this article at http://blog.dmbcllc.com/2007/12/05/using-the-web-deployment-project-2008-ctp/ which shows how to get this all working under Visual Studio 2008. The Web Deployment Project for 2008 breaks some of the following instructions and the post tells you what you need to do to get it all working again.
Several months ago I was looking for a way to using ASP.NET 2.0 coding techniques to produce a DotNetNuke PA. Everything I found either said you have to use codebehind files like we did in ASP.NET 1.x or you have to ship the code as part of the PA. At the time, I could not find any instructions on how to create a DotNetNuke PA using ASP.NET 2.0 coding techniques without having to ship the code with it. In fact, I was basically informed that this could not be done.
My requirements were simple:
- Using ASP.NET 2.0 coding techniques to create my DNN module.
- End up with the same two DLLs (Module and SQL Provider) that I had when I created modules for DNN 3.x.
- Not be required to ship any of my source, except the ASCX/ASPX files.
While working on the solution, I got the added benefit of also being able to create the programmable assembly zip file as part of my build process.
What follows is a step by step explaination of how to achieve my goal.
Required Tools
Instructions
- Download and install the prerequisite tools mentioned above.
- Copy the DNN Install Version into a subdirectory of your web directory (normally, c:\inetpub\wwwroot\yourdirectory) and then make yourdirectory and application directory.
- Run the site to get DNN all set correctly. Install as few of the modules as you can get away with for the module you will be building.
- Open Visual Studio and open the website you just created
- To create a new module, right click the root of the web site project in Visual Studio and select "Add New Item…" from the menu.
- Under "My Templates" select "DotNetNuke Dynamic Module," fill in the name and press the "Add" button. You can create the module in either VB or C#.
- A screen will display telling you what modifications you need to make that the item template was unable to make. Make sure you follow these instructions.
- Make sure you change all the references to "YourCompany" in the aspx, cs, vb, and dnn files to something that represents your company.
- Build the site to make sure you don't have any errors.
- You can do most of the building and testing of your website at this point because it will all basically work the same now as it will when we deploy it. You can use the standard, ASP.NET 2.0, way of building web sites to build and test your modules, complete with the code beside model that is the standard way of building websites in ASP.NET 2.0. However, there are a few items you'll need to code up a little differently due to the fact that we want to use the provider model that the DotNetNuke guys have handed to us:
- Any DotNetNuke development solution will be composed of at least 4 projects:
- The main DNN Development site
- A Base Provider project that will have one abstract class in it. This should be a standard DLL project, not a web site.
- A SQL Provider project that implements the abstract class in the Base Provider project above.
- The deployment project. This is the project we will be spending the most time on as this is the key to making this system work.
- Create a new project, within the same solution, to hold your Base Provider code. Remember, you should create this as a class library project. I name mine baseModuleNameProvider, but you can name it whatever you want as long as it is clear to you while you are working on the code.
- Remove the Class1.cs (or vb) file it automatically created for you.
- We will ultimately be merging all of the DLLs that were created for our module code in the DNN project with the Base Provider DLL, for everything to work correctly, we need to set the output DLL filename to the name we want to use for the merged DLL. So, name it something like companyName.ModuleName.dll. In my case, I named a store module, dmbcllc.Store.dll.
- Your Base Provider project should reference the DotNetNuke.dll in the DNN Project's bin directory.
- Copy the DataProvider.cs file out of the App_Code/ModuleName directory in the DNN Project and put the file in this project.
- You can either move the *Info.cs (vb) and *Controller.cs (vb) into this project, or you can leave them in the App_Code/ModuleName directory. I personally keep them in App_Code/ModuleName and the remaining directions will assume you have them there as well. So, you may want to keep them there at least until you understand how this works.
- Create another class library project, still in the same solution, for your SQL Provider code. I normally call mine SQLModuleNameProvider.
- Remove the Class1.cs (vb) file it automatically created for you.
- Your SQL Provider project should reference the DotNetNuke.dll and the Microsoft.ApplicationsBlock.Data.dll in the DNN Project's bin directory as well as the Base Provider project.
- Copy the SQLDataProvider.cs (vb) file out of the App_Code/ModuleName directory into this project. I also keep my 01.00.00.SqlDataProvider file in this project as well.
- Complete the initial setup of your project by adding references tp the Base Provider project and the SQL Provider project in your DNN Project
- Once again, you should rebuild the solution to make sure everything still compiles. Don't forget to make whatever appropriate namespace changes you may need.
- Now the magic beings. You will want to create a deployment project by selecting the DNN Project in the solution explorer and then selecting the "Build" > "Add Web Deployment Project…" from the menu. Once you select the menu option, a dialog will appear prompting you for the name of the deployment project and the location you want it to be in. I find it easiest to place the project under inetpub/wwwroot like any other web project, but it really will not matter where you place it.
- Once the web deployment project has been created, right click the project and select "Properties" from the menu. We need to change a few of the defaults the deployment project has setup.
- When the properties dialog displays, select "Output Assemblies" from the tree on the lefthand side of the dialog. Then, select the radio button that says, "Merge each individual folder output to it's own assembly." You'll probably also want to set the file and assembly version here, so check that box and enter the values.
- Next, select "Deployment" from the tree and check the "Remove the App_Folder from output location" checkbox.
- Press "OK" to exit.
- To get the rest of the magic to happen we need to drop into the msbuild source. To do this, right click on the deployment project and select, "Open Project File" from the menu. This should bring up an XML file in a text editor. Once you have it open, you should see the following two lines:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
You'll want to insert a line between them so that they end up looking like:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" /> <PropertyGroup>
This will allow this project to use the build extensions we installed earlier.
- You should also see several "PropertyGroup" sections followed by an empty ItemGroup section. Within this item group section we will want to exclude files from being part of the build. For example, there are VB files that are part of the DNN install that we don't want to be part of the build, so we need to exclude them. Since I work in Csharp, I can tell it to just exclude all of the VB files, but if you work in VB, you will need to exclude them explicitly. You'll also want to exclude the following:
- Anything under the admin directory
- Anything under the portals directory
- Any ASPX or ASCX files in the root directory of the website project
- Anything under the components directory
- Anything under the config directory
- Anything under the images directory
- Anything under the install directory
- Anything under the js directory
- Anything under the providers directory
- Anything under any module directories that are not the module you are building the deployment project, and ultimately a PA, for.
- My ItemGroup section looks like this:
<ItemGroup>
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\admin\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Portals\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.vb" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\*.as?x" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Components\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Config\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\images\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\install\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\js\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\providers\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\DesktopModules\HTML\**\*.*" />
<ExcludeFromBuild Include="$(SourceWebPhysicalPath)\DesktopModules\Links\**\*.*" />
</ItemGroup>
If you are not familiar with msBuild, the \**\*.* means "Any files in the directory or in any of it's subdirectories."
- If you build the deployment project now, you should end up with files in the directory you specified when you created the deployment project. As a note, you may want to set the deployment project up so that it only builds in release mode. Otherwise, you'll have to go through this extra build step while you are developing, which can significantly slow you down.
- There are two directories in the deployment project that we are interested in. The bin directory should have a dll for all the files in the App_Code/ModuleName directory, a DLL for all of the files in the DesktopModules/ModuleName directory, a DLL for the base provider project and a DLL for the SQL provider project. There should also be ASCX and RESX files that are part of our module under the DesktopModules directory. If we setup everything correctly, there should only be one directory there.
- The first thing we need to do is merge the App_Code/ModuleName, DesktopModules/ModuleName and base Provider DLLs into one DLL. We can do this by entering a post build step into the deployment project XML file. So, go back to that file and uncomment this code:
<Target Name="AfterBuild">
</Target>
Add the following post build line between the opening and closing Target element:
<Exec Command=""C:\Program Files\Microsoft\ILMerge\ILMerge.exe" /ndebug /target:dll
/out:C:\Inetpub\wwwroot\deployDirectory\installation\baseDLLName.dll C:\Inetpub\wwwroot\deployDirectory\Release\bin\baseDLLName.dll /log C:\Inetpub\wwwroot\deployDirectory\Release\bin\App_SubCode_ModuleName.dll C:\Inetpub\wwwroot\deployDirectory\Release\bin\DesktopModules.ModuleName.dll" />
(Note: that should all be on one line.)
This will merge the three DLLs together. Remember that we needed to name the baseProvider DLL what we ultimately want to be the DLL in our PA? This is why. ILMerge takes the first DLL in our list and makes it the main dll. Since the base DLL's name has to remain the same so that the SQL Provider DLL can find it when it goes to load it dynamically, we need for it to be the primary DLL in our merge.
- Next, we need to copy all of the files that we want to be part of our installation into the same installation directory that the ilmerge program created for us when we did the ilmerge. You do that with the Exec element like this:
<Exec Command="copy .\release\bin\ModuleName.SqlDataProvider.dll .\installation\*.*" />
You'll want to put all of the DLL's, ASCX, RESX, DNN, SQL Install files and image files, as well as any other supporting files you may have into the installation directory using a similar command. You don't need to copy the DLLs that we merged above.
- Once you have all of the files in the directory that we need to install, there are really only two things left. First, we need to do a fixup of the ASCX files in our project. When the initial compile occurred, the compiler changed the ASCX files to point to the codebehind file it created to go along with the ASCX files, but remember, we just merged that file with the base provider dll. So, now we need to go into those ASCX files and change them so that they are pointing to the merged dll. So, first MSBuild needs a named list of all the ASCX files. Since I occassionally also have ASPX files I'm installing too, I use the following lines, which should be placed immediately after your copy lines inside the Target element:
<CreateItem Include="installation\*.as?x">
<Output ItemName="as_xFiles" TaskParameter="Include" />
</CreateItem>
And then, right after that line, you'll want a line that tells the build process to go into each of those files and look for a reference to the old dll and replace it with a reference to the new dll:
<FileUpdate Files="@(as_xFiles)" IgnoreCase="true" Regex="DesktopModules\.ModuleName" ReplacementText="baseModuleDLLName" />
Note: I do not have the ".dll" at the end of either the Regex value or the ReplacementText value.
- Finally, we'll want to create a programable assembly out of all of this. This is simply a matter of taking all of the files in the installation directory and putting them in a zip file. We can have the build process do this for us by building another named list of all of the files in the installation directory:
<CreateItem Include="installation\*.*">
<Output ItemName="ZipFiles" TaskParameter="Include" />
</CreateItem>
And then telling the build process to make a zip file out of them:
<Zip ZipFileName="dmbcllcStore.zip" WorkingDirectory="installation" Files="@(ZipFiles)" />
- Assuming you've done everything, the way I've intended, you should now be able to build your solution and end up with a zip file that you can install into DotNetNuke.
While it may be obvious to some, it probably needs to be stated that you'll want to create a separate deployment project for each module you create. But, you can create multiple modules using the same DNN project. You'll just need to exclude the files from all of the other modules in each web deployment project you create.
|
 |
|
|
|
|