//====================================================================================================
        /// <summary>
        /// get a portal feature available to developers that provides tool for creating portals
        /// </summary>
        /// <param name="CP"></param>
        /// <returns></returns>
        string getDevTool(CPBaseClass CP, portalDataClass portal, string frameRqs )
        {
            string body = "Hello World";
            try
            {
                string section;
                //
                // this is a feature list, display the feature list
                //
                formSimpleClass content = new formSimpleClass();
                content.title = "Developer Tool";
                content.body = "";
                //
                // process snapshot tool
                //
                if(CP.Doc.GetText("button")=="Take Snapshot")
                {
                    CPCSBaseClass cs = CP.CSNew();
                    if (cs.Open("portals", "ccguid=" + CP.Db.EncodeSQLText(portal.guid)))
                    {
                        System.Web.Script.Serialization.JavaScriptSerializer msJson = new System.Web.Script.Serialization.JavaScriptSerializer() ;
                        string configJson = msJson.Serialize(portal);
                        cs.SetField("defaultConfigJson", configJson);
                    }
                    cs.Close();

                }
                //
                // output snapshot tool
                //
                section = "<h3>Portal Snapshot</h3>";
                section += "<p>Click the snapshot button to save the current features for this portal in the portal's default configuration field.</p>";
                section += CP.Html.Button("button", "Take Snapshot");
                section += "<p>Modify Portal and Portal Features data directly</p>";
                section += "<ul>";
                section += "<li><a href=\"?cid=" + CP.Content.GetID("Portals") + "\">Portals</a></li>";
                section += "<li><a href=\"?cid=" + CP.Content.GetID("Portal Features") + "\">Portal Features</a></li>";
                section += "</ul>";
                section = CP.Html.Form(section,"","","",frameRqs);
                content.body += section;
                //
                //
                //
                body = content.getHtml(CP);
            }
            catch (Exception ex)
            {
                CP.Site.ErrorReport(ex, "exception in loadPortal");
            }
            return body;
        }
 //====================================================================================================
 /// <summary>
 /// create a feature list box
 /// </summary>
 /// <param name="CP"></param>
 /// <param name="feature"></param>
 /// <returns></returns>
 string getFeatureList(CPBaseClass CP, portalDataClass portal,  portalFeatureDataClass feature, string frameRqs )
 {
     string returnBody = "";
     string items = "";
     string qs;
     try
     {
         string activeNavHeading;
         activeNavHeading = feature.heading;
         formSimpleClass content = new formSimpleClass();
         foreach (KeyValuePair<string, portalFeatureDataClass> kvp in portal.featureList)
         {
             portalFeatureDataClass liFeature = kvp.Value;
             if ((liFeature.parentFeatureId == feature.id) && (liFeature.parentFeatureId != 0))
             {
                 string featureHeading = liFeature.heading;
                 if (string.IsNullOrEmpty(featureHeading))
                 {
                     featureHeading = liFeature.name;
                 }
                 if (liFeature.dataContentId != 0)
                 {
                     qs = frameRqs;
                     qs = CP.Utils.ModifyQueryString(qs, "addonid", "", false);
                     qs = CP.Utils.ModifyQueryString(qs, rnDstFeatureGuid, "", false);
                     qs = CP.Utils.ModifyQueryString(qs, "cid", liFeature.dataContentId.ToString());
                     items += "<li><a target=\"_blank\" href=\"?" + qs + "\">" + featureHeading + "</a></li>";
                 }
                 else
                 {
                     qs = frameRqs;
                     qs = CP.Utils.ModifyQueryString(qs, rnDstFeatureGuid, liFeature.guid);
                     items += "<li><a href=\"?" + qs + "\">" + featureHeading + "</a></li>";
                 }
             }
         }
         content.title = feature.heading;
         content.body = "<ul class=\"afwButtonList\">" + items + "</ul>";
         returnBody = content.getHtml(CP);
     }
     catch (Exception ex)
     {
         CP.Site.ErrorReport(ex, "adminFramework.portalClass.getFeatureList exception");
     }
     return returnBody;
 }
 //====================================================================================================
 /// <summary>
 /// get the portal html provided the Sql select criteria for portal. Blank returns the first order by id.
 /// </summary>
 /// <param name="CP"></param>
 /// <param name="portalSelectSqlCriteria"></param>
 /// <returns></returns>
 public string getHtml(CPBaseClass CP, string portalSelectSqlCriteria)
 {
     string returnHtml = "";
     //
     try {
         if (!CP.User.IsAdmin) {
             returnHtml = blockedMessage;
         } else {
             CPBlockBaseClass form = CP.BlockNew();
             string frameRqs = CP.Doc.RefreshQueryString;
             adminFramework.pageWithNavClass innerForm = new adminFramework.pageWithNavClass();
             string body = "";
             CPCSBaseClass cs = CP.CSNew();
             string dstFeatureGuid = CP.Doc.GetText(rnDstFeatureGuid);
             portalFeatureDataClass feature;
             int portalid = CP.Doc.GetInteger(rnPortalId);
             string activeNavHeading = "";
             //
             // build portal
             //
             portalDataClass portal = loadPortalFromDb(CP, portalSelectSqlCriteria);
             frameRqs = CP.Utils.ModifyQueryString(frameRqs, rnSetPortalId, portal.id.ToString(), true);
             //
             // portal interface - add tabs
             //
             foreach (KeyValuePair<string, portalFeatureDataClass> kvp in portal.featureList) {
                 feature = kvp.Value;
                 if (feature.parentFeatureId == 0)
                 {
                     innerForm.addNav();
                     innerForm.navCaption = feature.heading;
                     innerForm.navLink = "?" + CP.Utils.ModifyQueryString(frameRqs, rnDstFeatureGuid, feature.guid);
                 }
             }
             //
             // add developer tab
             //
             if (CP.User.IsDeveloper)
             {
                 if (portal.featureList.ContainsKey(devToolGuid))
                 {
                     CP.Site.ErrorReport("loadPortalFromDb, the portal [" + portal.name + "] appears to have the devTool feature saved in either the Db features or the defaultConfig. This is not allowed.");
                 }
                 else
                 {
                     innerForm.addNav();
                     innerForm.navCaption = "Developer Tool";
                     innerForm.navLink = "?" + CP.Utils.ModifyQueryString(frameRqs, rnDstFeatureGuid, devToolGuid);
                 }
             }
             //
             // add linked features
             //
             if (portal.linkedPortals.Count > 0)
             {
                 foreach(portalDataClass linkedPortal in portal.linkedPortals)
                 {
                     innerForm.addNav();
                     innerForm.navCaption = linkedPortal.name;
                     innerForm.navLink = "?" + CP.Utils.ModifyQueryString(frameRqs, rnSetPortalId, linkedPortal.id.ToString() );
                 }
             }
             //
             //   execute feature, if it returns empty, display default feature
             //
             if (dstFeatureGuid == devToolGuid)
             {
                 //
                 // execute developer tools
                 //
                 CP.Doc.AddRefreshQueryString(rnDstFeatureGuid, devToolGuid);
                 body = getDevTool(CP, portal, frameRqs );
                 activeNavHeading = "Developer Tool";
             }
             else
             {
                 if (portal.featureList.ContainsKey(dstFeatureGuid))
                 {
                     //
                     // add feature guid to frameRqs so if the feature uses ajax, the featureGuid will be part of it
                     // add feature guid to rqs so if an addon is used that does not support frameRqs it will work
                     //
                     feature = portal.featureList[dstFeatureGuid];
                     frameRqs = CP.Utils.ModifyQueryString(frameRqs, rnDstFeatureGuid, feature.guid);
                     if (feature.addonId != 0)
                     {
                         //
                         // feature is an addon, execute it
                         //
                         CP.Doc.SetProperty(rnFrameRqs, frameRqs);
                         CP.Doc.AddRefreshQueryString(rnDstFeatureGuid, feature.guid);
                         body = CP.Utils.ExecuteAddon(feature.addonId.ToString());
                         //if (feature.parentFeatureId == 0)
                         //{
                         //    activeNavHeading = feature.heading;
                         //}
                         //else
                         //{
                         //    foreach (KeyValuePair<string, portalFeatureDataClass> kvp in portal.featureList)
                         //    {
                         //        portalFeatureDataClass parentFeature = kvp.Value;
                         //        if (parentFeature.id == feature.parentFeatureId)
                         //        {
                         //            activeNavHeading = parentFeature.heading;
                         //            //
                         //            // if feature returned empty and it is in a feature list, execute the feature list
                         //            //
                         //            if (string.IsNullOrEmpty(body))
                         //            {
                         //                body = getFeatureList(CP, portal, parentFeature, frameRqs);
                         //            }
                         //        }
                         //    }
                         //}
                     }
                     else if (feature.dataContentId != 0)
                     {
                         //
                         // this is a data content feature -- should not be here, link should have taken them to the content
                         //
                         CP.Response.Redirect("?cid=" + feature.dataContentId.ToString());
                         formSimpleClass content = new formSimpleClass();
                         content.title = feature.heading;
                         content.body = "Redirecting to content";
                         body = content.getHtml(CP);
                     }
                     else
                     {
                         //
                         // this is a feature list, display the feature list
                         //
                         body = getFeatureList(CP, portal, feature, frameRqs);
                     }
                     //
                     // set active heading
                     //
                     if (feature.parentFeatureId == 0)
                     {
                         activeNavHeading = feature.heading;
                     }
                     else
                     {
                         foreach (KeyValuePair<string, portalFeatureDataClass> kvp in portal.featureList)
                         {
                             portalFeatureDataClass parentFeature = kvp.Value;
                             if (parentFeature.id == feature.parentFeatureId)
                             {
                                 activeNavHeading = parentFeature.heading;
                                 //
                                 // if feature returned empty and it is in a feature list, execute the feature list
                                 //
                                 if (string.IsNullOrEmpty(body))
                                 {
                                     body = getFeatureList(CP, portal, parentFeature, frameRqs);
                                 }
                             }
                         }
                     }
                     if (feature.addPadding)
                     {
                         body = CP.Html.div(body, "", "afwBodyPad", "");
                     }
                 }
             }
             if (string.IsNullOrEmpty(body)) {
                 //
                 // if the feature turns blank, run the default feature
                 //
                 if (portal.defaultFeature!=null)
                 {
                     feature = portal.defaultFeature;
                     activeNavHeading = feature.heading;
                     frameRqs = CP.Utils.ModifyQueryString(frameRqs, rnDstFeatureGuid, feature.guid);
                     CP.Doc.SetProperty(rnFrameRqs, frameRqs);
                     CP.Doc.AddRefreshQueryString(rnDstFeatureGuid, feature.guid);
                     body = CP.Utils.ExecuteAddon(feature.addonId.ToString());
                     if (feature.addPadding)
                     {
                         body = CP.Html.div(body, "", "afwBodyPad", "");
                     }
                 }
                 if(string.IsNullOrEmpty(body))
                 {
                     formSimpleClass simple = new formSimpleClass();
                     simple.body = "This portal feature has no content.";
                     body = simple.getHtml(CP);
                 }
             }
             innerForm.setActiveNav(activeNavHeading);
             //
             //Assemble
             //
             innerForm.body = CP.Html.div(body, "" ,"" , "afwBodyFrame");
             innerForm.title = portal.name;
             innerForm.isOuterContainer = true;
             returnHtml = innerForm.getHtml(CP);
             //
             // assemble body
             //
             CP.Doc.AddHeadStyle(Properties.Resources.styles);
             CP.Doc.AddHeadJavascript("var afwFrameRqs='" + frameRqs + "';");
             CP.Doc.AddHeadJavascript(Properties.Resources.javascript);
         }
     } catch (Exception ex) {
         CP.Site.ErrorReport(ex, "error in Contensive.Addons.aoAccountBilling.adminClass.execute");
     }
     return returnHtml;
 }