These articles were originally written by Jarick Rager from KeySysConsulting.

Over many years of programming, I have used various methods to streamline creating web applications. The efforts were geared towards one goal: produce applications in a repeatable and efficient manner. Often, clients wanted to integrate a public facing website with internal web applications. The main purpose was to allow clients to be self-sufficient in maintaining the content of the website but not interfere with the applications.

Those thoughts led to researching various open source content management systems and code generation tools. I had written a couple of code generation tools over the years using different architectures and techniques. The obvious benefit was that the code on one project was architected and had been tested on other projects. However, I wanted a solution that would provide more CMS features and integrate robust application architecture.

We came across mojoPortal and CodeSmith with the netTiers framework. They are front-runners for addressing these concepts. The only problem is that they do not integrate out-of-the-box. After a few brainstorming sessions, it seemed not only possible but absolutely essential that we find a solution to integrate these two awesome products.

Over the next few days, I will post the results of our integration efforts. This will be aimed at describing the overall process and not meant as a de-facto standard. There will be various implementation strategies that we choose for the sake of “making it work." If you discover better ways to make it work, please share in a constructive manner.

With that being said, let’s begin our journey…

Prepare for Integration (Part 1)

We will start with a simple example that uses one table in a SQL Database. ACMETools is the name of the database. Acme.Tools is the namespace used when the netTiers code was generated using CodeSmith. I will use the Organization table from the database in the example.

NOTE: If you want to debug along with the mojoPortal code, include the netTiers projects associated with the DLLs in the mojoPortal solution file.

  1. Create a database called ACMETools.
  2. Create a user named ACMEToolsUser with the password ACMETools.
  3. Provide the ACMEToolsUser with DBO permissions to the ACMETools database.
  4. Create the Organization table in the ACMETools database.
    	CREATE TABLE [dbo].[Organization](
    	[OrganizationID] [int] IDENTITY(1,1) NOT NULL,
    	[Name] [varchar](50) NOT NULL,
    	[AddressLine1] [varchar](50) NULL,
    	[AddressLine2] [varchar](50) NULL,
    	[City] [varchar](50) NULL,
    	[State] [varchar](2) NULL,
    	[Zip] [varchar](10) NULL,
    	CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED
    	(
    	[OrganizationID] ASC
    	)WITH (PAD_INDEX= OFF, STATISTICS_NORECOMPUTE= OFF, IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS= ON, ALLOW_PAGE_LOCKS= ON) ON [PRIMARY]
    	) ON [PRIMARY]
  5. Use CodeSmith to generate the netTiers code. Recommended initial settings to change before generating code:
    • ChooseSourceDatabase=ACMETools
    • OutputDirectory= <Select Your Output Location>
    • RootNameSpace=Acme.Tools
    • SourceTables= <Select the Organization table>
    • DotNetVersion= v4
    • ExecuteSql=true (to generate stored procedures for your selected table)
    • IncludeDatabaseFeatures=SQLServer2005
    • BusinessLogicLayerNameSpace=BLL
    • DataAccessNameSpace=DAL
  6. Build the netTiers solution.
  7. Copy the following dlls from the netTiers Website bin folder to the mojoPortal web bin folder.
    • Acme.Tools.BLL.dll
    • Acme.Tools.DAL.dll
    • Acme.Tools.DAL.SqlClient.dll
    • Acme.Tools.Web.dll
    • Microsoft.Practices.EnterpriseLibrary.Common.dll
    • Microsoft.Practices.EnterpriseLibrary.Data.dll
  8. Include the contents of the following sections from the netTiers web.config file to the mojoPortal web.config file.
    1. configSections – You will need to add the section tag.
      <configSections>
      	<sectionname="ACME.Tools.DAL"type="ACME.Tools.DAL.Bases.KeySysServiceSection, ACME.Tools.DAL"allowDefinition="MachineToApplication"restartOnExternalChanges="true" />
      </configSections>
    2. connectionStrings - You will need to add the connectionStrings section.
      <connectionStrings>
      	<addname="ACME.Tools.DAL.ConnectionString"connectionString="Data Source=localhost;Initial Catalog=ACMETools;User ID=ACMEToolsUser;Password=ACMETools" />
      </connectionStrings>
    3. SqlProvider section – You will need to add this section.
      <ACME.Tools.DALdefaultProvider="SqlNetTiersProvider">
      	<providers>
      			<addname="SqlNetTiersProvider"type="ACME.Tools.DAL.SqlClient.SqlKeySysProvider, ACME.Tools.DAL.SqlClient" connectionStringName="ACME.Tools.DAL.ConnectionString"
      			providerInvariantName="System.Data.SqlClient"
      			entityFactoryType="ACME.Tools.BLL.EntityFactory"
      			useEntityFactory="true" enableEntityTracking="false" enableMethodAuthorization="false"
      			useStoredProcedure="false" defaultCommandTimeout="30"
      			/>
      	</providers>
      </ACME.Tools.DAL>
    4. Add the following tag prefixes to the controls section.
      <controls>
      	<addtagPrefix="asp"namespace="System.Web.UI"assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      	<addtagPrefix="data"namespace="ACME.Tools.Web.Data"assembly="ACME.Tools.Web" />
      	<addtagPrefix="data"namespace="ACME.Tools.Web.UI"assembly="ACME.Tools.Web" />
      </controls>
      
    5. Add the EntityTransactionModule tag to the httpModules section.
      <httpModules>
      	<addname="EntityTransactionModule"type="ACME.Tools.Web.Data.EntityTransactionModule, ACME.Tools.Web" />
      </httpModules>
      
  9. Open the netTiers generated Visual Studio solution file to modify the code.
    1. Create a folder named mojoPortal under the Admin folder.
    2. Create two folders under the mojoPortal folder named PageControls and UserControls.
    3. Copy the contents of the netTiers generated UserControls folder to the mojoPortal\UserControls folder. This will make it easier to copy the files to the mojoPortal later.
    4. CodeSmith / netTiers genrates two pages for each table selected in your code generation. In this example, it created Organization.aspx and OrganizationEdit.aspx for the Organization table.
    5. Copy the netTiers generated Organization.aspx and the OrganizationEdit.aspx files to the mojoPortal\PageControls folder. Do not copy the associated code-behind (*.cs) files.
    6. Rename the mojoPortal\PageControls\Organization.aspx file to OrganizationListPage.ascx.
    7. Rename the mojoPortal\PageControls\OrganizationEdit.aspx file to OrganizationEditPage.ascx.

Modify the netTiers Code for the mojoPortal Site (Part 2)

So far, we have shown how to lay a foundation for integrating mojoPortal and netTiers generated code. Now, we will continue the integration by showing the changes we need to make to the generated code.

  1. Modify the OrganizationListPage.ascx file
    1. Change the Page declaration to a Control declaration. Notice in the Control declaration that we inherit from the mojoPortal.Web.SiteModuleControl.
      <%@ Page Language="C#" Theme="Default" MasterPageFile="~/MasterPages/admin.master"AutoEventWireup="true" CodeFile="Organization.aspx.cs" Inherits="Organization"Title="Organization List" %>
      <%@ Control Language="C#" ClassName="OrganizationListPage"Inherits="mojoPortal.Web.SiteModuleControl" %>
    2. Copy the code from the netTiers Organization.aspx.cs file to the OrganizationListPage.ascx. In the ascx file, add the <script runat="server"> tag. This should be placed after the Control declaration.
      <script runat="server">
      	protected void Page_Load(object sender, EventArgs e)
      	{
        		FormUtil.RedirectAfterUpdate(gvOrganization, "Organization.aspx?page={0}");
        		FormUtil.SetPageIndex(gvOrganization, "page");
        		FormUtil.SetDefaultButton((Button)gvspOrganization.FindControl("cmdSearch"));
      	}
      	protected void gvOrganization_SelectedIndexChanged(object sender, EventArgs e)
      	{
        		string urlParams = string.Format("OrganizationId={0}",gvOrganization.SelectedDataKey.Values[0]);
        		Response.Redirect("OrganizationEdit.aspx?" + urlParams, true);
      	}
      </script>
    3. Remove the Content tags for the header content and the main content. Don’t forget to remove the closing tags!
      <asp:Content ID="Content2" ContentPlaceHolderID="cphHeader" Runat="Server">Organization List</asp:Content>
      <asp:Content ID="Content1" ContentPlaceHolderID="cphMain" Runat="Server">
      	...
      </asp:Content>
  2. Modify the OrganizationEditPage.ascx file
    1. Change the Page declaration to a Control declaration. Notice in the Control declaration that we inherit from the mojoPortal.Web.SiteModuleControl.
      <%@ Page Language="C#" Theme="Default" MasterPageFile="~/MasterPages/admin.master"AutoEventWireup="true" CodeFile="Organization.aspx.cs" Inherits="Organization"Title="Organization List" %>
      <%@ Control Language="C#" ClassName="OrganizationEditPage"Inherits="mojoPortal.Web.SiteModuleControl" %>
    2. Add the Import statements
      <%@ Import Namespace="System.Globalization" %>
      <%@ Import Namespace="mojoPortal.Business" %>
      <%@ Import Namespace="mojoPortal.Business.WebHelpers" %>
      <%@ Import Namespace="mojoPortal.Web.Framework" %>
      <%@ Import Namespace="mojoPortal.Web.Controls" %>
      <%@ Import Namespace="mojoPortal.Web.Editor" %>
      <%@ Import Namespace="mojoPortal.Net" %>
    3. Copy the code from the netTiers Organization.aspx.cs file to the OrganizationListPage.ascx. In the ascx file, add the <script runat="server"> tag. This should be placed after the Control declaration at the top of the file. If the Organization table is related to another table, the code will have a SelectedIndexChanged event for each related table.
      <script runat="server">
      	protected void Page_Load(object sender, EventArgs e)
      	{
      	  FormUtil.RedirectAfterInsertUpdate(FormView1, "OrganizationEdit.aspx?{0}",OrganizationDataSource);
      	  FormUtil.RedirectAfterAddNew(FormView1, "OrganizationEdit.aspx");
      	  FormUtil.RedirectAfterCancel(FormView1, "Organization.aspx");
      		FormUtil.SetDefaultMode(FormView1, "OrganizationId");
      	}
      </script>
    4. Remove the Content tags for the header content and the main content. Don’t forget the closing tags!
      <asp:Content ID="Content2" ContentPlaceHolderID="cphHeader" Runat="Server">Organization - Add/Edit</asp:Content>
         <asp:Content ID="Content1" ContentPlaceHolderID="cphMain" Runat="Server">
    5. Place the following code where the Content tags were located.
      <portal:mojoPanel ID="mp1" runat="server" ArtisteerCssClass="art-Post"RenderArtisteerBlockContentDivs="true">
      			<mp:CornerRounderTop id="ctop1" runat="server" />
      			<asp:Panel ID="pnlWrapper" runat="server" CssClass="art-Post-inner panelwrapper mymodule">
      			<asp:UpdatePanel ID="upGallery" UpdateMode="Conditional" runat="server">
      			<ContentTemplate>
      			<portal:ModuleTitleControl id="Title1" runat="server" />
      			<portal:mojoPanel ID="MojoPanel1" runat="server" ArtisteerCssClass="art-PostContent">
      			<asp:Panel ID="pnlMyClass" runat="server" CssClass="modulecontent">
    6. Change the path where the page is looking for the controls. Basically, replace Admin with Modules.
      <EditItemTemplatePaths>
      			<data:TemplatePath Path="~/Admin/UserControls/OrganizationFields.ascx" />
      			</EditItemTemplatePaths>
      			<InsertItemTemplatePaths>
      			<data:TemplatePath Path="~/Admin/UserControls/OrganizationFields.ascx" />
      			</InsertItemTemplatePaths>

      To

      <EditItemTemplatePaths>
      	<data:TemplatePath Path="~/Modules/UserControls/OrganizationFields.ascx" />
      </EditItemTemplatePaths>
      <InsertItemTemplatePaths>
      	<data:TemplatePath Path="~/Modules/UserControls/OrganizationFields.ascx" />
      </InsertItemTemplatePaths>
    7. Replace the closing </asp:Content>tag with the following:
      				</asp:Panel>
      				</portal:mojoPanel>
      			</ContentTemplate>
      		</asp:UpdatePanel>
      	</asp:Panel>
      </portal:mojoPanel>

      NOTE: If your tables had Foreign Keys to other tables, netTiers automatically creates drop down lists for you. Watch for these in the code so you can correct the page names if need be.

Create the mojoPortal Pages (Part 3)

So far, we have shown how to lay a foundation for integrating mojoPortal and netTiers generated code and the changes needed to the generated code.

Finally, we will show the steps for creating the pages and using the controls from the netTiers generated code.

  1. Copy the folder and files from the netTiers Admin\mojoPortal folder to the mojoPortal Modules folder. This will contain the PageControls and the UserControls folders. You will have to FTP the files if you are not running the mojoPortal site locally or on a network machine.
  2. Sign in to the mojoPortal sign using an Administrator level account.
  3. Click Administration.
  4. Click Advanced Tools.
  5. Click Feature Installation/Configuration.
  6. Click Add New Feature.
  7. Enter the necessary information to add a feature
    1. Feature Name Resource Key – OrganizationListPage
    2. Resource File – leave blank
    3. Control Source – Modules/PageControls/OrganizationListPage.ascx
    4. Feature Guid – leave the generated Guid in place. It is a good idea to copy the Guid and paste as a comment in the code for your control.
    5. You can leave everything else as is.
    6. Click the Update button.
  8. The control will now appear in the list of features.
  9. Click New Page
    1. Parent Page – select Home.
    2. Page Name – Organization.aspx.
    3. Page Title Override – Organization Search.
    4. Url - ~/Ogranization.aspx.
    5. Select the other options as desired. Just leave the defaults.
    6. Click Create New Page.
  10. Click Add/Remove Features On This Page
    1. Feature – Select OrganizationListPage
    2. Title – Search Organization
    3. Location – Center
    4. Click Create New Content

That creates the Search\List page for the Organization. Next, we will follow the same process for creating the OrganizationEdit page.

  1. Click Administration.
  2. Click Advanced Tools.
  3. Click Feature Installation/Configuration.
  4. Click Add New Feature.
  5. Enter the necessary information to add a feature
    1. Feature Name Resource Key – OrganizationEditPage
    2. Resource File – leave blank
    3. Control Source – Modules/PageControls/OrganizationEditPage.ascx
    4. Feature Guid – leave the generated Guid in place. It is a good idea to copy the Guid and paste as a comment in the code for your control.
    5. You can leave everything else as is.
    6. Click the Update button.
  6. The control will now appear in the list of features.
  7. Click New Page
    1. Parent Page – select Home.
    2. Page Name – OrganizationEdit.aspx.
    3. Page Title Override – Organization Edit.
    4. Url - ~/OgranizationEdit.aspx.
    5. Leave the defaults for the other options.
    6. Click Create New Page.
  8. Click Add/Remove Features On This Page
    1. Feature – Select OrganizationEditPage
    2. Title – Organization
    3. Location – Center
    4. Click Create New Content

Summary

We hope this helps generate ideas for you to integrate mojoPortal and netTiers. We would love to hear and share ideas with others out there that are trying to accomplish the same goal.