Пример #1
0
        private RuleInfo GenerateRule(
            string displayName,
            int value,
            int scoreId,
            string ruleCondition,
            RuleTypeEnum ruleType,
            string ruleParameter  = null,
            bool belongsToPersona = true)
        {
            var codeName = ValidationHelper.GetCodeName(displayName, 100);
            var ruleInfo = RuleInfoProvider.GetRules().WithCodeName(codeName).FirstOrDefault();

            if (ruleInfo != null)
            {
                return(ruleInfo);
            }

            var ruleObj = new RuleInfo
            {
                RuleScoreID          = scoreId,
                RuleDisplayName      = displayName,
                RuleName             = codeName,
                RuleValue            = value,
                RuleType             = ruleType,
                RuleParameter        = ruleParameter,
                RuleCondition        = ruleCondition,
                RuleBelongsToPersona = belongsToPersona
            };

            RuleInfoProvider.SetRuleInfo(ruleObj);
            return(ruleObj);
        }
Пример #2
0
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        scoreId = QueryHelper.GetInteger("scoreid", 0);
        rule    = RuleInfoProvider.GetRuleInfo(QueryHelper.GetInteger("ruleid", 0));
        EditForm.OnBeforeSave        += new EventHandler(EditForm_OnBeforeSave);
        EditForm.RedirectUrlAfterSave = "Tab_Rules_Edit.aspx?ruleid={%EditedObject.ID%}&scoreid=" + scoreId + "&saved=1";
        InitHeaderActions();
    }
Пример #3
0
        /// <summary>Performs scoring objects and rules generation.</summary>
        public void Generate()
        {
            if (ScoreInfoProvider.GetScores().WhereEquals("ScoreName", "EngagementAndBusinessFit")
                .WhereFalse("ScoreBelongsToPersona").TopN(1).FirstOrDefault() != null)
            {
                return;
            }

            var scoreObj = new ScoreInfo
            {
                ScoreDisplayName = "Engagement and business fit",
                ScoreName        = "EngagementAndBusinessFit",
                ScoreDescription =
                    "Measures the fit and interest of B2B prospects on the site. Fit is measured by demographics and geographics. Interest is measured by behavior on the site that can be tied to B2B activities, such as visiting the 'Partnership' section of the site or providing a phone number.",
                ScoreEnabled           = true,
                ScoreStatus            = ScoreStatusEnum.RecalculationRequired,
                ScoreEmailAtScore      = 20,
                ScoreNotificationEmail = "*****@*****.**"
            };

            ScoreInfoProvider.SetScoreInfo(scoreObj);
            var treeNode = DocumentHelper.GetDocuments().All().Culture("en-US").Path("/Partnership").Columns("NodeID")
                           .OnCurrentSite().TopN(1).FirstOrDefault();

            if (treeNode != null)
            {
                var rule = GenerateRule("Visited the Partnership section", 5, scoreObj.ScoreID,
                                        "<condition>\r\n  <activity name=\"pagevisit\">\r\n    <field name=\"ActivityCreated\">\r\n      <settings>\r\n        <seconddatetime>1/1/0001 12:00:00 AM</seconddatetime>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityNodeID\">\r\n      <value>" +
                                        treeNode.NodeID +
                                        "</value>\r\n    </field>\r\n    <field name=\"ActivityURL\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityTitle\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityComment\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityCampaign\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityURLReferrer\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityABVariantName\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityMVTCombinationName\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n  </activity>\r\n  <wherecondition>(ActivityType='pagevisit') AND ([ActivityNodeID] = " +
                                        treeNode.NodeID + ")</wherecondition>\r\n</condition>", RuleTypeEnum.Activity, "pagevisit", false);
                rule.RuleIsRecurring = true;
                rule.RuleMaxPoints   = 15;
                RuleInfoProvider.SetRuleInfo(rule);
            }

            var bizFormInfo = BizFormInfoProvider.GetBizFormInfo("BusinessCustomerRegistration", _mSite.SiteID);

            if (bizFormInfo != null)
            {
                GenerateRule("Submitted the business registration form", 15, scoreObj.ScoreID,
                             BuildMacroRuleCondition("{%Rule(\"(Contact.SubmittedForm(\\\"" + bizFormInfo.FormName +
                                                     "\\\", ToInt(0)))\", \"&lt;rules&gt;&lt;r pos=\\\"0\\\" par=\\\"\\\" op=\\\"and\\\" n=\\\"CMSContactHasSubmittedSpecifiedFormInLastXDays\\\" &gt;&lt;p n=\\\"_perfectum\\\"&gt;&lt;t&gt;has&lt;/t&gt;&lt;v&gt;&lt;/v&gt;&lt;r&gt;0&lt;/r&gt;&lt;d&gt;select operation&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;p n=\\\"days\\\"&gt;&lt;t&gt;#enter days&lt;/t&gt;&lt;v&gt;0&lt;/v&gt;&lt;r&gt;0&lt;/r&gt;&lt;d&gt;enter days&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;p n=\\\"item\\\"&gt;&lt;t&gt;" +
                                                     bizFormInfo.FormName + "&lt;/t&gt;&lt;v&gt;" + bizFormInfo.FormName +
                                                     "&lt;/v&gt;&lt;r&gt;1&lt;/r&gt;&lt;d&gt;select form&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;/r&gt;&lt;/rules&gt;\")%}"),
                             RuleTypeEnum.Macro, null, false);
            }

            GenerateRule("Provided phone number", 10, scoreObj.ScoreID,
                         "<condition>\r\n  <attribute name=\"ContactBusinessPhone\">\r\n    <params>\r\n      <ContactBusinessPhoneOperator>9</ContactBusinessPhoneOperator>\r\n    </params>\r\n  </attribute>\r\n  <wherecondition>([ContactBusinessPhone] &lt;&gt; N'' AND [ContactBusinessPhone] IS NOT NULL)</wherecondition>\r\n</condition>",
                         RuleTypeEnum.Attribute, "ContactBusinessPhone");
            RecalculateScores();
        }
Пример #4
0
        private void GenerateCafeOwnerPersona()
        {
            var infoObj = PersonaInfoProvider.GetPersonaInfoByCodeName(PERSONA_CAFE_OWNER);

            if (infoObj == null)
            {
                infoObj = new PersonaInfo
                {
                    PersonaDisplayName = "Tony, the Cafe Owner",
                    PersonaName        = PERSONA_CAFE_OWNER,
                    PersonaDescription =
                        "Tony has been running his own cafe for the last 7 years. He always looks at ways of improving the service he provides.\r\n\r\nHe offers coffee that he sources from several roasteries. In addition to that, he also sells brewing machines, accessories and grinders for home use.",
                    PersonaPointsThreshold     = 15,
                    PersonaPictureMetafileGUID = new Guid("220C65BA-2CED-4347-9615-8CF69EAC20E5"),
                    PersonaEnabled             = true
                };
                PersonaInfoProvider.SetPersonaInfo(infoObj);
            }

            var treeNode = DocumentHelper.GetDocuments().All().Culture("en-US").Path("/Partnership").Columns("NodeID")
                           .OnCurrentSite().TopN(1).FirstOrDefault();

            if (treeNode != null)
            {
                var rule = GenerateRule("Visited the Partnership section", 5, infoObj.PersonaScoreID,
                                        "<condition>\r\n  <activity name=\"pagevisit\">\r\n    <field name=\"ActivityCreated\">\r\n      <settings>\r\n        <seconddatetime>1/1/0001 12:00:00 AM</seconddatetime>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityNodeID\">\r\n      <value>" +
                                        treeNode.NodeID +
                                        "</value>\r\n    </field>\r\n    <field name=\"ActivityURL\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityTitle\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityComment\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityCampaign\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityURLReferrer\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityABVariantName\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n    <field name=\"ActivityMVTCombinationName\">\r\n      <settings>\r\n        <operator>0</operator>\r\n      </settings>\r\n    </field>\r\n  </activity>\r\n  <wherecondition>(ActivityType='pagevisit') AND ([ActivityNodeID] = " +
                                        treeNode.NodeID + ")</wherecondition>\r\n</condition>", RuleTypeEnum.Activity, "pagevisit");
                rule.RuleIsRecurring = true;
                rule.RuleMaxPoints   = 15;
                RuleInfoProvider.SetRuleInfo(rule);
            }

            var infoByName = ProviderHelper.GetInfoByName("cms.form", "BusinessCustomerRegistration", _mSite.SiteID);

            if (infoByName != null)
            {
                var obj = infoByName.GetValue("FormName");
                GenerateRule("Submitted the business registration form", 15, infoObj.PersonaScoreID,
                             BuildMacroRuleCondition("{%Rule(\"(Contact.SubmittedForm(\\\"" + obj +
                                                     "\\\", ToInt(0)))\", \"&lt;rules&gt;&lt;r pos=\\\"0\\\" par=\\\"\\\" op=\\\"and\\\" n=\\\"CMSContactHasSubmittedSpecifiedFormInLastXDays\\\" &gt;&lt;p n=\\\"_perfectum\\\"&gt;&lt;t&gt;has&lt;/t&gt;&lt;v&gt;&lt;/v&gt;&lt;r&gt;0&lt;/r&gt;&lt;d&gt;select operation&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;p n=\\\"days\\\"&gt;&lt;t&gt;#enter days&lt;/t&gt;&lt;v&gt;0&lt;/v&gt;&lt;r&gt;0&lt;/r&gt;&lt;d&gt;enter days&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;p n=\\\"item\\\"&gt;&lt;t&gt;" +
                                                     obj + "&lt;/t&gt;&lt;v&gt;" + obj +
                                                     "&lt;/v&gt;&lt;r&gt;1&lt;/r&gt;&lt;d&gt;select form&lt;/d&gt;&lt;vt&gt;text&lt;/vt&gt;&lt;tv&gt;0&lt;/tv&gt;&lt;/p&gt;&lt;/r&gt;&lt;/rules&gt;\")%}"),
                             RuleTypeEnum.Macro, null, false);
            }

            GenerateRule("Gmail penalization", -10, infoObj.PersonaScoreID,
                         "<condition>\r\n  <attribute name=\"ContactEmail\">\r\n    <value>gmail.com</value>\r\n    <params>\r\n      <ContactEmailOperator>6</ContactEmailOperator>\r\n    </params>\r\n  </attribute>\r\n  <wherecondition>[ContactEmail] LIKE N'%gmail.com'</wherecondition>\r\n</condition>",
                         RuleTypeEnum.Attribute, "ContactEmail");
        }
Пример #5
0
        private RuleConflictInfo FindConflictsCore(RuleSet baselineRuleSet, RuleSet targetRuleSet, params string[] ruleSetDirectories)
        {
            string[] directories = this.ruleSetSearchDirectories
                                   .Union(ruleSetDirectories)
                                   .Union(new[]
            {
                Path.GetDirectoryName(baselineRuleSet.FilePath),
                Path.GetDirectoryName(targetRuleSet.FilePath)
            }).ToArray();

            // RuleProviders are used in practice for IncludeAll purposes i.e. AllRule.ruleset will be
            // included with the specified action. In out cases only care about the baseline so we could create
            // a wrapper that provides the baseline rules, but in the context of the problem this is not required
            // since we will be able to find that the rules were missing just by diffing with the results from
            // GetEffectiveRules, see more details below.
            RuleInfoProvider[] providers = new RuleInfoProvider[0];

            // Underlying implementation details of GetEffectiveRules:
            // The method will return a list of rules, some are the same as specified, and for some the Action will change
            // according to the merge rules:

            // 1. If there's an <IncludeAll Action="..." /> then all the provider's rules will include all the rules
            // with the specified Action (can't be None or Default).
            //
            // 2. Then the includes will be take into account (essentially the same flow 1-3, recursively):
            //    a. If the Include Action is None -> will not be included
            //    b. If the Include Action is Default -> rule actions remains as defined
            //    b. otherwise it will get the Action from the Include
            //  Once the Include rule Action is determined it will be merged but could only change to more strict value !
            //
            // 3. Lastly the file-level rules are added with their Action (overriding any previous settings).
            //
            // To summarize in practical terms:
            // (●) IncludeAll - will not impact us because all the baseline rules will be merged on top of (1)
            //  and will either be more strict or the IncludeAll action will be more strict
            //  => either way won't weaken.
            //
            // (●) By default i.e. the way we generate the targetRuleSet (which we expect it to be the project level ruleset),
            // the includes cannot weaken the base line ruleset (which we expect it to be the solution level ruleset)
            // due to the include merge rules which prefer strictness and the fact that we use Default as the Include Action.
            //
            // (●) The only thing that can weaken the rules in practice, in the default case, are ruleset level rules
            // i.e what you get when you modify the ruleset by using the ruleset editor UI.
            //
            // (●) In the none default case, when the user decides to manually edit the file, setting the baseline include
            // to None or removing it will use the other Includes' Action settings which could weaken the target ruleset.
            //
            // With that in mind, we will find "conflicts" of two types - rule with weaker Action or a missing rule.
            // (assuming that all the rules were found with the help of ruleSetDirectories).
            //
            // In terms of how to fix the conflict...  we could either just add all the conflicted rules into the project. That
            // will not be optimal in terms of the user or the rebind/update experience. A better approach would be something like:
            // 1. Reset the baseline Include to Action=Default
            // 2. If there are still conflicts, remove all the conflicting rules which are directly on target ruleset.
            // At this point we should not have any conflicts, so there's should not be a need to add the remaining conflicting
            // rules directly under the target with Action=TheExpectedAction

            var effectiveRulesMap = targetRuleSet.GetEffectiveRules(directories, providers, this.EffectiveRulesErrorHandler)
                                    .ToDictionary(r => r.FullId, StringComparer.OrdinalIgnoreCase);

            Dictionary <RuleReference, RuleAction> weakenedRules = baselineRuleSet.Rules.Select(r =>
            {
                RuleReference reference;
                if (effectiveRulesMap.TryGetValue(r.FullId, out reference))
                {
                    Debug.Assert(reference.Action != RuleAction.None, "Expected to be found in the missing set");

                    if (IsBaselineWeakend(r.Action, reference.Action))
                    {
                        return(new
                        {
                            Rule = reference,
                            ExpectedAction = r.Action
                        });
                    }
                }

                return(null);
            }).Where(r => r != null).ToDictionary(r => r.Rule, r => r.ExpectedAction);

            var missingRules = baselineRuleSet.Rules.Where(r => r.Action != RuleAction.None && !effectiveRulesMap.ContainsKey(r.FullId));

            return(new RuleConflictInfo(missingRules, weakenedRules));
        }
        private RuleConflictInfo FindConflictsCore(RuleSet baselineRuleSet, RuleSet targetRuleSet, params string[] ruleSetDirectories)
        {
            string[] directories = this.ruleSetSearchDirectories
                .Union(ruleSetDirectories)
                .Union(new[]
                {
                    Path.GetDirectoryName(baselineRuleSet.FilePath),
                    Path.GetDirectoryName(targetRuleSet.FilePath)
                }).ToArray();

            // RuleProviders are used in practice for IncludeAll purposes i.e. AllRule.ruleset will be 
            // included with the specified action. In out cases only care about the baseline so we could create
            // a wrapper that provides the baseline rules, but in the context of the problem this is not required
            // since we will be able to find that the rules were missing just by diffing with the results from 
            // GetEffectiveRules, see more details below.
            RuleInfoProvider[] providers = new RuleInfoProvider[0];

            // Underlying implementation details of GetEffectiveRules:
            // The method will return a list of rules, some are the same as specified, and for some the Action will change 
            // according to the merge rules:

            // 1. If there's an <IncludeAll Action="..." /> then all the provider's rules will include all the rules 
            // with the specified Action (can't be None or Default).
            //
            // 2. Then the includes will be take into account (essentially the same flow 1-3, recursively):
            //    a. If the Include Action is None -> will not be included
            //    b. If the Include Action is Default -> rule actions remains as defined
            //    b. otherwise it will get the Action from the Include
            //  Once the Include rule Action is determined it will be merged but could only change to more strict value !
            // 
            // 3. Lastly the file-level rules are added with their Action (overriding any previous settings).
            //
            // To summarize in practical terms: 
            // (●) IncludeAll - will not impact us because all the baseline rules will be merged on top of (1)
            //  and will either be more strict or the IncludeAll action will be more strict 
            //  => either way won't weaken.
            // 
            // (●) By default i.e. the way we generate the targetRuleSet (which we expect it to be the project level ruleset),
            // the includes cannot weaken the base line ruleset (which we expect it to be the solution level ruleset)
            // due to to the include merge rules which prefer strictness and the fact that we use Default as the Include Action.
            // 
            // (●) The only thing that can weaken the rules in practice, in the default case, are ruleset level rules 
            // i.e what you get when you modify the ruleset by using the ruleset editor UI.
            // 
            // (●) In the none default case, when the user decides to manually edit the file, setting the baseline include
            // to None or removing it will use the other Includes' Action settings which could weaken the target ruleset.
            // 
            // With that in mind, we will find "conflicts" of two types - rule with weaker Action or a missing rule.
            // (assuming that all the rules were found with the help of ruleSetDirectories).
            // 
            // In terms of how to fix the conflict...  we could either just add all the conflicted rules into the project. That 
            // will not be optimal in terms of the user or the rebind/update experience. A better approach would be something like:
            // 1. Reset the baseline Include to Action=Default
            // 2. If there are still conflicts, remove all the conflicting rules which are directly on target ruleset.
            // At this point we should not have any conflicts, so there's should not be a need to add the remaining conflicting 
            // rules directly under the target with Action=TheExpectedAction

            var effectiveRulesMap = targetRuleSet.GetEffectiveRules(directories, providers, this.EffectiveRulesErrorHandler)
                .ToDictionary(r => r.FullId, StringComparer.OrdinalIgnoreCase);

            Dictionary<RuleReference, RuleAction> weakenedRules = baselineRuleSet.Rules.Select(r =>
            {
                RuleReference reference;
                if (effectiveRulesMap.TryGetValue(r.FullId, out reference))
                {
                    Debug.Assert(reference.Action != RuleAction.None, "Expected to be found in the missing set");

                    if (IsBaselineWeakend(r.Action, reference.Action))
                    {
                        return new
                        {
                            Rule = reference,
                            ExpectedAction = r.Action
                        };
                    }
                }

                return null;
            }).Where(r => r != null).ToDictionary(r => r.Rule, r => r.ExpectedAction);

            var missingRules = baselineRuleSet.Rules.Where(r => r.Action != RuleAction.None && !effectiveRulesMap.ContainsKey(r.FullId));

            return new RuleConflictInfo(missingRules, weakenedRules);
        }
Пример #7
0
        private IEnumerable <KeyValuePair <string, string> > GetMetricData()
        {
            string stringData = null;
            IEnumerable <KeyValuePair <string, string> > tupleData = null;

            // Gather data for each row, return special message if data is null
            switch (MetricCodeName)
            {
            // Categories
            case MetricDataEnum.support_metrics:
            case MetricDataEnum.support_metrics_system:
            case MetricDataEnum.support_metrics_environment:
            case MetricDataEnum.support_metrics_counters:
            case MetricDataEnum.support_metrics_ecommerce:
            case MetricDataEnum.support_metrics_tasks:
            case MetricDataEnum.support_metrics_eventlog:
                return(null);

                #region System

            case MetricDataEnum.support_metrics_system_version:
                stringData = CMSVersion.GetVersion(true, true, true, true);
                break;

            case MetricDataEnum.support_metrics_system_appname:
                stringData = SettingsHelper.AppSettings["CMSApplicationName"];
                break;

            case MetricDataEnum.support_metrics_system_instancename:
                stringData = SystemContext.InstanceName;
                break;

            case MetricDataEnum.support_metrics_system_physicalpath:
                stringData = SystemContext.WebApplicationPhysicalPath;
                break;

            case MetricDataEnum.support_metrics_system_apppath:
                stringData = SystemContext.ApplicationPath;
                break;

            case MetricDataEnum.support_metrics_system_uiculture:
                stringData = LocalizationContext.CurrentUICulture.CultureName;
                break;

            case MetricDataEnum.support_metrics_system_installtype:
                stringData = SystemContext.IsWebApplicationProject ? "Web App" : "Web site";
                break;

            case MetricDataEnum.support_metrics_system_portaltemplatepage:
                stringData = URLHelper.PortalTemplatePage;
                break;

            case MetricDataEnum.support_metrics_system_timesinceapprestart:
                stringData = (DateTime.Now - CMSApplication.ApplicationStart).ToString(@"dd\:hh\:mm\:ss");
                break;

            case MetricDataEnum.support_metrics_system_discoveredassemblies:
                tupleData = AssemblyDiscoveryHelper.GetAssemblies(true).Select((a, i) => GetKeyValuePair(i, a.FullName));
                break;

            case MetricDataEnum.support_metrics_system_targetframework:
                HttpRuntimeSection httpRuntime = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
                stringData = httpRuntime.TargetFramework;
                break;

            case MetricDataEnum.support_metrics_system_authmode:
                AuthenticationSection Authentication = ConfigurationManager.GetSection("system.web/authentication") as AuthenticationSection;
                stringData = Authentication?.Mode.ToString();
                break;

            case MetricDataEnum.support_metrics_system_sessionmode:
                SessionStateSection SessionState = ConfigurationManager.GetSection("system.web/sessionState") as SessionStateSection;
                stringData = SessionState?.Mode.ToString();
                break;

            case MetricDataEnum.support_metrics_system_debugmode:
                CompilationSection Compilation = ConfigurationManager.GetSection("system.web/compilation") as CompilationSection;
                stringData = Compilation?.Debug.ToString();
                break;

            case MetricDataEnum.support_metrics_system_runallmanagedmodules:
                var xmlDoc = new System.Xml.XmlDocument();
                xmlDoc.Load(URLHelper.GetPhysicalPath("~/Web.config"));
                stringData = xmlDoc.SelectSingleNode("/configuration/system.webServer/modules").Attributes["runAllManagedModulesForAllRequests"]?.Value;
                break;

                #endregion System

                #region Environment

            case MetricDataEnum.support_metrics_environment_trustlevel:

                AspNetHostingPermissionLevel trustLevel = AspNetHostingPermissionLevel.None;

                if (!SystemContext.IsWebSite)
                {
                    trustLevel = AspNetHostingPermissionLevel.Unrestricted;
                }

                // Check the trust level by evaluation of levels
                foreach (AspNetHostingPermissionLevel permissionLevel in new[] {
                    AspNetHostingPermissionLevel.Unrestricted,
                    AspNetHostingPermissionLevel.High,
                    AspNetHostingPermissionLevel.Medium,
                    AspNetHostingPermissionLevel.Low,
                    AspNetHostingPermissionLevel.Minimal
                })
                {
                    try
                    {
                        new AspNetHostingPermission(permissionLevel).Demand();
                    }
                    catch (SecurityException)
                    {
                        continue;
                    }

                    trustLevel = permissionLevel;
                    break;
                }

                stringData = trustLevel.ToString();
                break;

            case MetricDataEnum.support_metrics_environment_iisversion:
                stringData = MetricServerVariables["SERVER_SOFTWARE"];
                break;

            case MetricDataEnum.support_metrics_environment_https:
                stringData = MetricServerVariables["HTTPS"];
                break;

            case MetricDataEnum.support_metrics_environment_windowsversion:
                using (RegistryKey versionKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
                {
                    var productName  = versionKey?.GetValue("ProductName");
                    var currentBuild = versionKey?.GetValue("CurrentBuild");
                    var releaseId    = versionKey?.GetValue("ReleaseId");

                    stringData = String.Format("{0}, build {1}, release {2}", productName.ToString(), currentBuild.ToString(), releaseId.ToString());
                }
                break;

            case MetricDataEnum.support_metrics_environment_netversion:
                using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
                {
                    var keyValue = ndpKey?.GetValue("Release");
                    if (keyValue != null)
                    {
                        var releaseKey = (int)keyValue;
                        if (releaseKey >= 461808)
                        {
                            stringData = "4.7.2 or later";
                        }
                        else
                        if (releaseKey >= 461308)
                        {
                            stringData = "4.7.1";
                        }
                        else
                        if (releaseKey >= 460798)
                        {
                            stringData = "4.7";
                        }
                        else
                        if (releaseKey >= 394802)
                        {
                            stringData = "4.6.2";
                        }
                        else
                        if (releaseKey >= 394254)
                        {
                            stringData = "4.6.1";
                        }
                        else
                        if (releaseKey >= 393295)
                        {
                            stringData = "4.6";
                        }
                        else
                        if (releaseKey >= 379893)
                        {
                            stringData = "4.5.2";
                        }
                        else
                        if (releaseKey >= 378675)
                        {
                            stringData = "4.5.1";
                        }
                        else
                        if (releaseKey >= 378389)
                        {
                            stringData = "4.5";
                        }
                    }
                }
                break;

            case MetricDataEnum.support_metrics_environment_sqlserverversion:
                var dtm = new TableManager(null);
                stringData = dtm.DatabaseServerVersion;
                break;

            case MetricDataEnum.support_metrics_environment_azure:
                var azureStats = new Dictionary <string, string>(4)
                {
                    { "Is a Cloud Service", (SettingsHelper.AppSettings["CMSAzureProject"] == "true").ToString("false") },
                    { "Is file system on Azure", (SettingsHelper.AppSettings["CMSExternalStorageName"] == "azure").ToString("false") },
                    { "Azure storage account", SettingsHelper.AppSettings["CMSAzureAccountName"] ?? String.Empty },
                    { "Azure CDN endpoint", SettingsHelper.AppSettings["CMSAzureCDNEndpoint"] ?? String.Empty }
                };

                tupleData = azureStats.Select(s => GetKeyValuePair(s.Key, s.Value));
                break;

            case MetricDataEnum.support_metrics_environment_amazon:
                var amazonStats = new Dictionary <string, string>(3)
                {
                    { "Is file system on Amazon", (SettingsHelper.AppSettings["CMSExternalStorageName"] == "amazon").ToString() },
                    { "Amazon bucket name", SettingsHelper.AppSettings["CMSAmazonBucketName"] ?? String.Empty },
                    { "Amazon public access", SettingsHelper.AppSettings["CMSAmazonPublicAccess"] ?? String.Empty },
                };

                tupleData = amazonStats.Select(s => GetKeyValuePair(s.Key, s.Value));
                break;

            case MetricDataEnum.support_metrics_environment_services:
                tupleData = ServiceManager.GetServices().Select(s => GetKeyValuePair(s.ServiceName, s.Status));
                break;

                #endregion Environment

                #region Counters

            case MetricDataEnum.support_metrics_counters_webfarmservers:
                stringData = CoreServices.WebFarm.GetEnabledServerNames().Count().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_stagingservers:
                stringData = ServerInfoProvider.GetServers().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_pagemostchildren:
                CMS.DocumentEngine.TreeProvider tree = new CMS.DocumentEngine.TreeProvider();

                var pageWithMostChildren = tree.SelectNodes().OnCurrentSite().Published()
                                           .ToDictionary(n => n, n => n.Children.Count)
                                           .Aggregate((l, r) => l.Value > r.Value ? l : r);

                tupleData = new[] { GetKeyValuePair(URLHelper.GetAbsoluteUrl("~" + pageWithMostChildren.Key.NodeAliasPath), pageWithMostChildren.Value) };
                break;

            case MetricDataEnum.support_metrics_counters_modules:
                stringData = ResourceInfoProvider.GetResources().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_medialibraries:
                stringData = MediaLibraryInfoProvider.GetMediaLibraries().WhereNull("LibraryGroupID").GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_activities:
                stringData = ActivityInfoProvider.GetActivities().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_contacts:
                stringData = ContactInfoProvider.GetContacts().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_contactgroups:
                stringData = ContactGroupInfoProvider.GetContactGroups().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_omrules:
                stringData = RuleInfoProvider.GetRules().GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_counters_products:
                stringData = SKUInfoProvider.GetSKUs(SiteContext.CurrentSiteID).WhereNull("SKUOptionCategoryID").GetCount().ToString();
                break;

                #endregion Counters

                #region Tasks

            case MetricDataEnum.support_metrics_tasks_webfarm:
                stringData = WebFarmTaskInfoProvider.GetWebFarmTasks()
                             .WhereLessThan("TaskCreated", DateTime.Now.AddDays(-1))
                             .GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_tasks_staging:
                stringData = StagingTaskInfoProvider.GetTasks()
                             .WhereLessThan("TaskTime", DateTime.Now.AddDays(-1))
                             .GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_tasks_integration:
                stringData = IntegrationTaskInfoProvider.GetIntegrationTasks()
                             .WhereLessThan("TaskTime", DateTime.Now.AddDays(-1))
                             .GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_tasks_scheduled:
                stringData = TaskInfoProvider.GetTasks()
                             .WhereTrue("TaskDeleteAfterLastRun")
                             .WhereLessThan("TaskNextRunTime", DateTime.Now.AddDays(-1))
                             .GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_tasks_search:
                stringData = SearchTaskInfoProvider.GetSearchTasks()
                             .WhereLessThan("SearchTaskCreated", DateTime.Now.AddDays(-1))
                             .GetCount().ToString();
                break;

            case MetricDataEnum.support_metrics_tasks_email:
                stringData = EmailInfoProvider.GetEmailCount("EmailStatus = 1 AND EmailLastSendResult IS NOT NULL").ToString();
                break;

                #endregion Tasks

                #region Event log

            case MetricDataEnum.support_metrics_eventlog_macroerrors:
                var macroErrors = EventLogProvider.GetEvents()
                                  .WhereEquals("Source", "MacroResolver")
                                  .WhereGreaterThan("EventTime", DateTime.Now.Subtract(TimeSpan.FromDays(7)))
                                  .OrderByDescending("EventTime")
                                  .TopN(10);

                tupleData = macroErrors.Select(e =>
                                               GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                               e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                               );
                break;

            case MetricDataEnum.support_metrics_eventlog_stagingerrors:
                var stagingErrors = EventLogProvider.GetEvents()
                                    .WhereEquals("Source", "staging")
                                    .WhereIn("EventType", new[] { "E", "W" })
                                    .WhereGreaterThan("EventTime", DateTime.Now.Subtract(TimeSpan.FromDays(7)))
                                    .OrderByDescending("EventTime")
                                    .TopN(10);

                tupleData = stagingErrors.Select(e =>
                                                 GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                                 e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                                 );
                break;

            case MetricDataEnum.support_metrics_eventlog_searcherrors:
                var searchErrors = EventLogProvider.GetEvents()
                                   .WhereEquals("Source", "search")
                                   .WhereIn("EventType", new[] { "E", "W" })
                                   .WhereGreaterThan("EventTime", DateTime.Now.Subtract(TimeSpan.FromDays(7)))
                                   .OrderByDescending("EventTime")
                                   .TopN(10);

                tupleData = searchErrors.Select(e =>
                                                GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                                e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                                );
                break;

            case MetricDataEnum.support_metrics_eventlog_contenterrors:
                var contentErrors = EventLogProvider.GetEvents()
                                    .WhereEquals("Source", "content")
                                    .WhereIn("EventType", new[] { "E", "W" })
                                    .WhereGreaterThan("EventTime", DateTime.Now.Subtract(TimeSpan.FromDays(7)))
                                    .OrderByDescending("EventTime")
                                    .TopN(10);

                tupleData = contentErrors.Select(e =>
                                                 GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                                 e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                                 );
                break;

            case MetricDataEnum.support_metrics_eventlog_exceptions:
                var exceptions = EventLogProvider.GetEvents()
                                 .WhereEquals("EventCode", "exception")
                                 .WhereGreaterThan("EventTime", DateTime.Now.Subtract(TimeSpan.FromDays(7)))
                                 .OrderByDescending("EventTime")
                                 .TopN(10);

                tupleData = exceptions.Select(e =>
                                              GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                              e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                              );
                break;

            case MetricDataEnum.support_metrics_eventlog_upgrade:

                EventLogInfo upgrade = EventLogProvider.GetEvents().WhereLike("Source", "upgrade%").FirstOrDefault();
                var          version = upgrade?.Source.Split(' ')[2];

                if (!String.IsNullOrEmpty(version))
                {
                    var parameters = new QueryDataParameters
                    {
                        { "@versionnumber", version }
                    };

                    var events = ConnectionHelper.ExecuteQuery("SupportHelper.CustomMetric.checkupgrade", parameters);

                    tupleData = (from DataRow row in events.Tables[0]?.Rows select row)
                                .Select(r => new EventLogInfo(r)).Select(e =>
                                                                         GetKeyValuePair(String.Format("{0} from {1} at {2} in {3}", e.EventCode, e.Source, e.EventTime, e.EventMachineName),
                                                                                         e.EventDescription.Length > CUTOFF ? e.EventDescription.Substring(0, CUTOFF) : e.EventDescription)
                                                                         );
                }
                break;

                #endregion Event log
            }

            if (tupleData?.Count() > 0)
            {
                return(tupleData);
            }

            if (stringData != null)
            {
                return(new[] { GetKeyValuePair(0, stringData) });
            }

            return(new[] { GetKeyValuePair(0, ResHelper.GetStringFormat("support.metrics.invalid", MetricDisplayName, MetricCodeName)) });
        }