DotNetNuke: User Log Viewer

 

Download: UserLogViewer_01.00.00_Install.zip (this link contains the install and source) (note: If using DNN4 install and run LinqPrep first. If using DNN5 follow these directions first)

A module intended to demonstrate the use of the "Contains" Linq extension method that allows you to handle complex parameter criteria with a single Linq query.

Using The Module

First enable the site log on your site, create a few test users and log into the site as those test users and click around for a bit to create some sample data. If you do not have any data the module will not show anything when you select the users.

After you install the module and place it on a page in your DNN site, you will see a list of the roles in your portal in the Role box.

When you select a role in the Role box, the users in that role will display in the Users box. You can hold down the Ctrl key and select multiple roles. The users in all the roles selected will show. If you click the *ALL* item (in either box) it will automatically select all the items in the box.

The module will display the number of requests for each of the users selected in the Users box. 

The Challenge

As a developer you are frequently tasked with providing the user the ability to enter parameters to query data. In this example we want to allow the user to select one or more roles and then one or more users in those roles. In addition, we want to provide the ability to select all the roles or all the users who match the selected roles.

A developer might assume they need to construct the logic this way:

A closer look however, will reveal:

In this example the following query is used:

        #region ShowEvents
        private void ShowEvents(string[] UserArray)
        {
            // Get the SiteLog as an IEnumerable list of type SiteLogInfo
            IEnumerable<SiteLogInfo> SiteLogList = GetSiteLog().Cast<SiteLogInfo>();

            // Query the SiteLogList by determining if the Array of users
            // passed to the method contain any of the users in the Site log
            SiteLogList = from users in SiteLogList
                          where UserArray.Contains(users.Name)
                          select users;

            // Show the list of users that match
            gvSiteLog.DataSource = SiteLogList;
            gvSiteLog.DataBind();
        } 
        #endregion
The UserArray that is passed as a parameter is the only parameter needed to perform the query no matter what criteria the user selected in the list boxes. The key is this line:
where UserArray.Contains(users.Name)
The Contains extension method allows you to create an array of criteria and test each record in your result set against that criteria to produce the final result set.

In this example, the role list is only used to filter the users. The users are the only item needed in the final query.

Even if additional criteria such as "start" and "end" date were added to the interface, that criteria would be passed directly to the final query still resulting in only one query.

The challenge then becomes "how to you make an interface to allow the user to easily filter among multiple interlocking criteria"? This module is offered as one example with most of the code show below: 

The Code

// DotNetNuke® - http://www.dotnetnuke.com
// Copyright (c) 2002-2009
// by DotNetNuke Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Roles;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Log.SiteLog;

namespace AdefWebserver.Modules.UserLogViewer
{
    public partial class View : PortalModuleBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if ((Page.IsPostBack == false))
                {
                    ShowRoles();
                }
            }
            catch (Exception ex)
            {
                Exceptions.ProcessModuleLoadException(this, ex);
            }
        }

        #region ShowRoles
        private void ShowRoles()
        {
            // Get all the Roles
            RoleController RoleController = new RoleController();
            ArrayList colArrayList = RoleController.GetRoles();

            // Create a ListItemCollection to hold the Roles 
            ListItemCollection colListItemCollection = new ListItemCollection();

            // Create the *All* option
            colListItemCollection.Add(GetAnAllListItem());

            // Add the Roles to the List
            foreach (RoleInfo Role in colArrayList)
            {
                ListItem RoleListItem = new ListItem();
                RoleListItem.Text = Role.RoleName;
                RoleListItem.Value = Role.RoleID.ToString();
                colListItemCollection.Add(RoleListItem);
            }

            // Add the Roles to the ListBox
            ListBoxRoles.DataSource = colListItemCollection;
            ListBoxRoles.DataBind();
        }
        #endregion

        #region ShowUsers
        private void ShowUsers(String[] SelectedItems)
        {
            // Get all users
            // If a portal has a lot of users you will want to replace this method with one that 
            // makes a direct call to the users table using Linq to SQL
            ArrayList arrAllUsers = UserController.GetUsers(PortalId);

            IEnumerable<UserInfo> Users = from User in arrAllUsers.Cast<UserInfo>()
                                          where UserIsInRole(SelectedItems, User.Roles) == true
                                          select User;

            // Create a ListItemCollection to hold the Users 
            ListItemCollection colListItemCollection = new ListItemCollection();

            // Create the *All* option
            colListItemCollection.Add(GetAnAllListItem());

            // Add the Users to the List
            foreach (UserInfo objUser in Users)
            {
                ListItem RoleListItem = new ListItem();
                RoleListItem.Text = objUser.DisplayName;
                RoleListItem.Value = objUser.FirstName + ' ' + objUser.LastName;
                colListItemCollection.Add(RoleListItem);
            }

            // Add the Users to the ListBox
            ListBoxUsers.DataSource = colListItemCollection;
            ListBoxUsers.DataBind();
        }
        #endregion

        #region ShowEvents
        private void ShowEvents(string[] UserArray)
        {
            // Get the SiteLog as an IEnumerable list of type SiteLogInfo
            IEnumerable<SiteLogInfo> SiteLogList = GetSiteLog().Cast<SiteLogInfo>();

            // Query the SiteLogList by determining if the Array of users
            // passed to the method contain any of the users in the Site log
            SiteLogList = from users in SiteLogList
                          where UserArray.Contains(users.Name)
                          select users;

            // Show the list of users that match
            gvSiteLog.DataSource = SiteLogList;
            gvSiteLog.DataBind();
        }
        #endregion

        #region ListBoxRoles_SelectedIndexChanged
        protected void ListBoxRoles_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Clear the SiteLog GridView
            gvSiteLog.DataSource = null;
            gvSiteLog.DataBind();

            // Get the selected items in ListBoxRoles
            IEnumerable<ListItem> SelectedListBoxItems = from li in ListBoxRoles.Items.Cast<ListItem>()
                                                         where li.Selected == true
                                                         select li;

            // Select all items in the list box if one of them is the "All" item (-1)
            if (SelectedListBoxItems.Count(X => X.Value == "-1") > 0)
            {
                // Select all items in the list box
                foreach (ListItem RoleListItem in ListBoxRoles.Items)
                {
                    RoleListItem.Selected = true;
                }
            }

            // Only try to load Users if there are selected Roles
            if (SelectedListBoxItems.Count() > 0)
            {
                // Create an array of the Role names and call ShowUsers
                ShowUsers(SelectedListBoxItems.Select(x => x.Text).ToArray());
            }
        }
        #endregion

        #region ListBoxUsers_SelectedIndexChanged
        protected void ListBoxUsers_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Get the selected items in ListBoxUsers
            IEnumerable<ListItem> SelectedListBoxItems = from li in ListBoxUsers.Items.Cast<ListItem>()
                                                         where li.Selected == true
                                                         select li;

            // Select all items in the list box if one of them is the "All" item (-1)
            if (SelectedListBoxItems.Count(X => X.Value == "-1") > 0)
            {
                // Select all items in the list box
                foreach (ListItem UserListItem in ListBoxUsers.Items)
                {
                    UserListItem.Selected = true;
                }
            }

            // Only try to load Events if there are selected Users
            if (SelectedListBoxItems.Count() > 0)
            {
                // Create an array of the Role names and call ShowEvents
                ShowEvents(SelectedListBoxItems.Select(X => X.Value).ToArray());
            }
        }
        #endregion

        #region GetSiteLog
        private IEnumerable GetSiteLog()
        {
            // Get the entire Site Log
            SiteLogController SiteLogController = new SiteLogController();
            // Call the core method to read the site log into a DataReader
            IDataReader SiteLog = SiteLogController.GetSiteLog(PortalId, "", 3, Convert.ToDateTime("1/1/1900"), DateTime.Now.AddDays(Convert.ToDouble(1)));

            // Use the DataRecord extension method to convert the DataReader to IEnumerable
            IEnumerable SiteLogList = (from row in SiteLog.DataRecord()
                                       select new SiteLogInfo
                                       {
                                           Name = (string)row[0],
                                           Requests = (int)row[1],
                                           LastRequest = Convert.ToDateTime(row[2])
                                       }).ToList();
            return SiteLogList;
        }
        #endregion

        #region UserIsInRole
        private bool UserIsInRole(string[] SelectedRoles, string[] RolesForUser)
        {
            bool boolRoleFound = false;
            foreach (string Role in SelectedRoles)
            {
                if (RolesForUser.Contains(Role))
                {
                    boolRoleFound = true;
                    break;
                }
            }

            return boolRoleFound;
        }
        #endregion

        #region GetAnAllListItem
        private static ListItem GetAnAllListItem()
        {
            ListItem ListItem = new ListItem();
            ListItem.Text = "*ALL*";
            ListItem.Value = "-1";
            return ListItem;
        }
        #endregion
    }
}

Summary

When faced with programming an interface that allows the user to select various complex parameters, a developer may feel they will need a lot of "if... then..." statements. Usually the query only needs the parameters from the final selection. This can easily be handled using the "Contains" Linq method.

You want to minimize the amount of code that you create whenever possible to minimize bugs and the time required for other developers to add enhancements. In addition, This module demonstrates helpful extension methods that allow you to transform Arraylists and IDataReaders that the DNN Core methods produce, into a format that can be used by Linq. Linq is always the best method to use rather than manipulating collections using loops.

Note: the module uses Linq but it does not use Linq to SQL.

[Back to: The ADefWebserver DotNetNuke HELP WebSite]

 


Buy DotNetNuke Modules from Snowcovered

 DotNetNuke Powered!DotNetNuke is a registered trademark of DotNetNuke Corporation.