C# 在ASP.NET MVC应用程序中记录用户活动

C# 在ASP.NET MVC应用程序中记录用户活动,c#,asp.net-mvc-4,architecture,C#,Asp.net Mvc 4,Architecture,我计划基于ActionFilterAttribute创建过滤器,以记录用户活动: public class LogAttribute : ActionFilterAttribute { public ActionType Type { get; set; } public override void OnResultExecuted(ResultExecutedContext filterContext) { // logic for log } }

我计划基于
ActionFilterAttribute
创建过滤器,以记录用户活动:

public class LogAttribute : ActionFilterAttribute
{
    public ActionType Type { get; set; }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
      // logic for log
    }
}
我想对控制器中的操作使用此属性。我想记录一些值
X,Y,Z
在我的视图中设置了哪个用户,以及一些与操作相关的信息。在这种情况下,我可能必须将这些X、Y、Z作为参数发送给我的操作,然后在属性代码中从ResultExecutedContext获取这些值。但这种方法让我有点困惑,因为我的每一个动作都有冗余的参数


从View到C#code,有没有好的方法来共享值?

值必须在某个时候由用户或代码进行设置。但是,您可以使用
会话
数组来包含这些值。它们将在登录会话期间保留

存储到会话

Session["key"] = "data";
后来在代码中

var val = Session["key"]; // val now has a value of "data";

我使用的是一个helper方法,它使用反射并将模型转储到一个字典中,这样您就不必将值复制到其他地方,所有内容都从一个地方“您的模型”发送

你可以用像

 DumpModel(model);    
使用这些值记录所需的内容,
我希望这有帮助

我可以通过以下方式实现这一点

创建一个表(名称-
Portal\u Logger
D\u MASTER

接下来,创建一个过滤器,用于跟踪用户的活动,如下所示

public class HomeController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult UserLandingPage()
    {
        return View();
    }
}


public class AdminController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult CreateUser()
    {
        return View();
    }
}


public class ReportController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult AppUtilization()
    {
        return View();
    }
}
LoggerActionFilter.cs

using System;
using System.Web.Mvc;
using System.Net;
using System.Linq;
using System.Net.Sockets;
using MyMvcApplication.Models.Entity;
using MyMvcApplication.Utilities;

namespace MyMvcApplication.Filters
{
    /// <summary>
    /// 
    /// </summary>
    public class LoggerActionFilter : ActionFilterAttribute
    {
        private static TimeZoneInfo INDIAN_ZONE = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Stores the Request in an Accessible object
            var request = filterContext.HttpContext.Request;
            var visitCount = Convert.ToInt64(filterContext.HttpContext.Session["LoggerActivityTracking"].ToString());
            // Generate an audit
            Portal_Logger aLogger = new Portal_Logger()
            {
                // Your Logger Identifier     
                LoggerId = Guid.NewGuid(),
                //Logged On User Id
                LogedUserId = Convert.ToInt32(filterContext.HttpContext.Session["LogedUserID"]),
                // The IP Address of the Request
                IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
                //Get the Web Page name(from the URL that was accessed)
                AreaAccessed = UserActivityUtility.GetWebPageName(request.RawUrl == "/"? "/Home/UserLandingPage" : request.RawUrl),
                // Creates our Timestamp
                Timestamp = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, INDIAN_ZONE),
                VisitorSessionId = visitCount
            };
            
            // Stores the Logger in the Database
            using (dbEntities context = new dbEntities())
            {
                if (aLogger.LogedUserId != null)
                {
                    aLogger.LogedUserEmpId = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Id).FirstOrDefault();
                    aLogger.LogedUserEmpName = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Name).FirstOrDefault();
                    aLogger.AccessedType = aLogger.AreaAccessed.Contains("Report") ? "Report" : "Page";
                }
                context.Portal_Logger.Add(aLogger);
                context.SaveChanges();
            }
            // Finishes executing the Logger as normal 
            base.OnActionExecuting(filterContext);
        }

    }
}
using System;       
namespace MyMvcApplication.Utilities
{
    public static class UserActivityUtility
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageName"></param>
        /// <returns></returns>
        public static string GetWebPageName(string pageName)
        {
            string formattedPageName = string.Empty;
            //For All user web pages
            if (pageName.Contains("UserLandingPage"))
            {
                formattedPageName = "Home - App Management";
            }            
            //For Report Web Pages 
            else if (pageName.Contains("AppUtilization"))
            {
                formattedPageName = "Application Utilization Report";
            }           
            else if (pageName.Contains("AlertReport"))
            {
                formattedPageName = "Alert Report";
            }                       
            else
            {
                formattedPageName = pageName;
            }
            return formattedPageName;
        }
    }
}
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE Procedure [dbo].[sp_Portal_GetUserLoginDetails_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN
        --EXEC sp_Portal_GetUserLoginDetails_Logger '2017-06-16','2017-06-16'
        SET NOCOUNT ON

        SELECT  u.LogedUserID,u.UserName,u.IPAddress,u.AreaAccessed,u.[Timestamp],u.LastLoggedInDay
        FROM 
        (
                SELECT  DISTINCT l.LogedUserID,e.Emp_Name as 'UserName',l.IPAddress,l.AreaAccessed,l.[Timestamp],l.LastLoggedInDay
                FROM 
                (
                        SELECT * 
                        FROM 
                        (
                            SELECT  Row_Number() Over ( PARTITION BY LogedUserID ORDER BY [Timestamp] DESC) As RowNum, LogedUserID,

                                    IPAddress,AreaAccessed,TIMESTAMP, DATEDIFF(D,TIMESTAMP,CURRENT_TIMESTAMP) AS 'LastLoggedInDay'
                            FROM    Portal_Logger 
                            WHERE   CAST([Timestamp] AS DATE) BETWEEN @FromDate AND @ToDate
                        ) t2
                    WHERE RowNum = 1
                ) l
                JOIN D_MASTER e on l.LogedUserID = e.User_Id                
        ) u     
        ORDER BY u.[Timestamp] DESC     
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_Portal_GetUserAccessedSummary_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN       
        --EXEC sp_Portal_GetUserAccessedSummary_Logger '2017-06-16','2017-06-16'

        SET NOCOUNT ON      
            SELECT  A.AreaAccessed,
                    COUNT(A.Timestamp) AS NoofTimeAccessed,
                    CONVERT(TIME(0), DATEADD(SECOND,SUM(SessionSeconds), 0)) AS TotalTimeSpent,
                    CONVERT(TIME(0), DATEADD(SECOND,AVG(SessionSeconds), 0)) AS AvgTimeSpent,
                    COUNT(DISTINCT LogedUserID) AS NoofUserAccessed
  
            FROM
            (
                SELECT  
                        A.AreaAccessed,A.Timestamp,
                        ISNULL(DATEDIFF(S,A.Timestamp,ISNULL(LEAD(A.Timestamp,1)OVER(PARTITION BY A.VisitorSessionId ORDER BY A.Timestamp),A.Timestamp)),0) AS SessionSeconds,
                        A.LogedUserID
        
                FROM    Portal_Logger A(NOLOCK)
                JOIN    D_MASTER B(NOLOCK) ON A.LogedUserID=B.User_Id
                WHERE   A.VisitorSessionId IS NOT NULL
                AND     CAST(A.Timestamp AS DATE) BETWEEN @FromDate AND @ToDate

            )A
            GROUP BY A.AreaAccessed
            ORDER BY NoofTimeAccessed DESC      
        SET NOCOUNT OFF
END
最后将该属性应用于控制器操作(您要跟踪哪些操作),如下所示

public class HomeController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult UserLandingPage()
    {
        return View();
    }
}


public class AdminController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult CreateUser()
    {
        return View();
    }
}


public class ReportController : Controller
{
    [LoggerActionFilter(Order = 1)]
    public ActionResult AppUtilization()
    {
        return View();
    }
}
下面是获取用户登录详细信息和页面访问摘要详细信息的“MS SQL StoredProcess”

用户登录详细信息

using System;
using System.Web.Mvc;
using System.Net;
using System.Linq;
using System.Net.Sockets;
using MyMvcApplication.Models.Entity;
using MyMvcApplication.Utilities;

namespace MyMvcApplication.Filters
{
    /// <summary>
    /// 
    /// </summary>
    public class LoggerActionFilter : ActionFilterAttribute
    {
        private static TimeZoneInfo INDIAN_ZONE = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Stores the Request in an Accessible object
            var request = filterContext.HttpContext.Request;
            var visitCount = Convert.ToInt64(filterContext.HttpContext.Session["LoggerActivityTracking"].ToString());
            // Generate an audit
            Portal_Logger aLogger = new Portal_Logger()
            {
                // Your Logger Identifier     
                LoggerId = Guid.NewGuid(),
                //Logged On User Id
                LogedUserId = Convert.ToInt32(filterContext.HttpContext.Session["LogedUserID"]),
                // The IP Address of the Request
                IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
                //Get the Web Page name(from the URL that was accessed)
                AreaAccessed = UserActivityUtility.GetWebPageName(request.RawUrl == "/"? "/Home/UserLandingPage" : request.RawUrl),
                // Creates our Timestamp
                Timestamp = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, INDIAN_ZONE),
                VisitorSessionId = visitCount
            };
            
            // Stores the Logger in the Database
            using (dbEntities context = new dbEntities())
            {
                if (aLogger.LogedUserId != null)
                {
                    aLogger.LogedUserEmpId = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Id).FirstOrDefault();
                    aLogger.LogedUserEmpName = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Name).FirstOrDefault();
                    aLogger.AccessedType = aLogger.AreaAccessed.Contains("Report") ? "Report" : "Page";
                }
                context.Portal_Logger.Add(aLogger);
                context.SaveChanges();
            }
            // Finishes executing the Logger as normal 
            base.OnActionExecuting(filterContext);
        }

    }
}
using System;       
namespace MyMvcApplication.Utilities
{
    public static class UserActivityUtility
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageName"></param>
        /// <returns></returns>
        public static string GetWebPageName(string pageName)
        {
            string formattedPageName = string.Empty;
            //For All user web pages
            if (pageName.Contains("UserLandingPage"))
            {
                formattedPageName = "Home - App Management";
            }            
            //For Report Web Pages 
            else if (pageName.Contains("AppUtilization"))
            {
                formattedPageName = "Application Utilization Report";
            }           
            else if (pageName.Contains("AlertReport"))
            {
                formattedPageName = "Alert Report";
            }                       
            else
            {
                formattedPageName = pageName;
            }
            return formattedPageName;
        }
    }
}
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE Procedure [dbo].[sp_Portal_GetUserLoginDetails_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN
        --EXEC sp_Portal_GetUserLoginDetails_Logger '2017-06-16','2017-06-16'
        SET NOCOUNT ON

        SELECT  u.LogedUserID,u.UserName,u.IPAddress,u.AreaAccessed,u.[Timestamp],u.LastLoggedInDay
        FROM 
        (
                SELECT  DISTINCT l.LogedUserID,e.Emp_Name as 'UserName',l.IPAddress,l.AreaAccessed,l.[Timestamp],l.LastLoggedInDay
                FROM 
                (
                        SELECT * 
                        FROM 
                        (
                            SELECT  Row_Number() Over ( PARTITION BY LogedUserID ORDER BY [Timestamp] DESC) As RowNum, LogedUserID,

                                    IPAddress,AreaAccessed,TIMESTAMP, DATEDIFF(D,TIMESTAMP,CURRENT_TIMESTAMP) AS 'LastLoggedInDay'
                            FROM    Portal_Logger 
                            WHERE   CAST([Timestamp] AS DATE) BETWEEN @FromDate AND @ToDate
                        ) t2
                    WHERE RowNum = 1
                ) l
                JOIN D_MASTER e on l.LogedUserID = e.User_Id                
        ) u     
        ORDER BY u.[Timestamp] DESC     
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_Portal_GetUserAccessedSummary_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN       
        --EXEC sp_Portal_GetUserAccessedSummary_Logger '2017-06-16','2017-06-16'

        SET NOCOUNT ON      
            SELECT  A.AreaAccessed,
                    COUNT(A.Timestamp) AS NoofTimeAccessed,
                    CONVERT(TIME(0), DATEADD(SECOND,SUM(SessionSeconds), 0)) AS TotalTimeSpent,
                    CONVERT(TIME(0), DATEADD(SECOND,AVG(SessionSeconds), 0)) AS AvgTimeSpent,
                    COUNT(DISTINCT LogedUserID) AS NoofUserAccessed
  
            FROM
            (
                SELECT  
                        A.AreaAccessed,A.Timestamp,
                        ISNULL(DATEDIFF(S,A.Timestamp,ISNULL(LEAD(A.Timestamp,1)OVER(PARTITION BY A.VisitorSessionId ORDER BY A.Timestamp),A.Timestamp)),0) AS SessionSeconds,
                        A.LogedUserID
        
                FROM    Portal_Logger A(NOLOCK)
                JOIN    D_MASTER B(NOLOCK) ON A.LogedUserID=B.User_Id
                WHERE   A.VisitorSessionId IS NOT NULL
                AND     CAST(A.Timestamp AS DATE) BETWEEN @FromDate AND @ToDate

            )A
            GROUP BY A.AreaAccessed
            ORDER BY NoofTimeAccessed DESC      
        SET NOCOUNT OFF
END
页面访问摘要详细信息

using System;
using System.Web.Mvc;
using System.Net;
using System.Linq;
using System.Net.Sockets;
using MyMvcApplication.Models.Entity;
using MyMvcApplication.Utilities;

namespace MyMvcApplication.Filters
{
    /// <summary>
    /// 
    /// </summary>
    public class LoggerActionFilter : ActionFilterAttribute
    {
        private static TimeZoneInfo INDIAN_ZONE = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Stores the Request in an Accessible object
            var request = filterContext.HttpContext.Request;
            var visitCount = Convert.ToInt64(filterContext.HttpContext.Session["LoggerActivityTracking"].ToString());
            // Generate an audit
            Portal_Logger aLogger = new Portal_Logger()
            {
                // Your Logger Identifier     
                LoggerId = Guid.NewGuid(),
                //Logged On User Id
                LogedUserId = Convert.ToInt32(filterContext.HttpContext.Session["LogedUserID"]),
                // The IP Address of the Request
                IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
                //Get the Web Page name(from the URL that was accessed)
                AreaAccessed = UserActivityUtility.GetWebPageName(request.RawUrl == "/"? "/Home/UserLandingPage" : request.RawUrl),
                // Creates our Timestamp
                Timestamp = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, INDIAN_ZONE),
                VisitorSessionId = visitCount
            };
            
            // Stores the Logger in the Database
            using (dbEntities context = new dbEntities())
            {
                if (aLogger.LogedUserId != null)
                {
                    aLogger.LogedUserEmpId = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Id).FirstOrDefault();
                    aLogger.LogedUserEmpName = context.D_MASTER
                        .Where(x => x.User_Id == aLogger.LogedUserId)
                        .Select(x => x.Emp_Name).FirstOrDefault();
                    aLogger.AccessedType = aLogger.AreaAccessed.Contains("Report") ? "Report" : "Page";
                }
                context.Portal_Logger.Add(aLogger);
                context.SaveChanges();
            }
            // Finishes executing the Logger as normal 
            base.OnActionExecuting(filterContext);
        }

    }
}
using System;       
namespace MyMvcApplication.Utilities
{
    public static class UserActivityUtility
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageName"></param>
        /// <returns></returns>
        public static string GetWebPageName(string pageName)
        {
            string formattedPageName = string.Empty;
            //For All user web pages
            if (pageName.Contains("UserLandingPage"))
            {
                formattedPageName = "Home - App Management";
            }            
            //For Report Web Pages 
            else if (pageName.Contains("AppUtilization"))
            {
                formattedPageName = "Application Utilization Report";
            }           
            else if (pageName.Contains("AlertReport"))
            {
                formattedPageName = "Alert Report";
            }                       
            else
            {
                formattedPageName = pageName;
            }
            return formattedPageName;
        }
    }
}
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE Procedure [dbo].[sp_Portal_GetUserLoginDetails_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN
        --EXEC sp_Portal_GetUserLoginDetails_Logger '2017-06-16','2017-06-16'
        SET NOCOUNT ON

        SELECT  u.LogedUserID,u.UserName,u.IPAddress,u.AreaAccessed,u.[Timestamp],u.LastLoggedInDay
        FROM 
        (
                SELECT  DISTINCT l.LogedUserID,e.Emp_Name as 'UserName',l.IPAddress,l.AreaAccessed,l.[Timestamp],l.LastLoggedInDay
                FROM 
                (
                        SELECT * 
                        FROM 
                        (
                            SELECT  Row_Number() Over ( PARTITION BY LogedUserID ORDER BY [Timestamp] DESC) As RowNum, LogedUserID,

                                    IPAddress,AreaAccessed,TIMESTAMP, DATEDIFF(D,TIMESTAMP,CURRENT_TIMESTAMP) AS 'LastLoggedInDay'
                            FROM    Portal_Logger 
                            WHERE   CAST([Timestamp] AS DATE) BETWEEN @FromDate AND @ToDate
                        ) t2
                    WHERE RowNum = 1
                ) l
                JOIN D_MASTER e on l.LogedUserID = e.User_Id                
        ) u     
        ORDER BY u.[Timestamp] DESC     
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_Portal_GetUserAccessedSummary_Logger]
(
@FromDate DATE,
@ToDate DATE
)
AS
BEGIN       
        --EXEC sp_Portal_GetUserAccessedSummary_Logger '2017-06-16','2017-06-16'

        SET NOCOUNT ON      
            SELECT  A.AreaAccessed,
                    COUNT(A.Timestamp) AS NoofTimeAccessed,
                    CONVERT(TIME(0), DATEADD(SECOND,SUM(SessionSeconds), 0)) AS TotalTimeSpent,
                    CONVERT(TIME(0), DATEADD(SECOND,AVG(SessionSeconds), 0)) AS AvgTimeSpent,
                    COUNT(DISTINCT LogedUserID) AS NoofUserAccessed
  
            FROM
            (
                SELECT  
                        A.AreaAccessed,A.Timestamp,
                        ISNULL(DATEDIFF(S,A.Timestamp,ISNULL(LEAD(A.Timestamp,1)OVER(PARTITION BY A.VisitorSessionId ORDER BY A.Timestamp),A.Timestamp)),0) AS SessionSeconds,
                        A.LogedUserID
        
                FROM    Portal_Logger A(NOLOCK)
                JOIN    D_MASTER B(NOLOCK) ON A.LogedUserID=B.User_Id
                WHERE   A.VisitorSessionId IS NOT NULL
                AND     CAST(A.Timestamp AS DATE) BETWEEN @FromDate AND @ToDate

            )A
            GROUP BY A.AreaAccessed
            ORDER BY NoofTimeAccessed DESC      
        SET NOCOUNT OFF
END

我认为在mvc中使用会话是不好的idea@Polaris这对我来说是个新闻——你有什么特别的原因认为它们是一个坏选择吗?@Polaris为什么是个坏主意?我希望我可以使用你的代码,但它不起作用。[AuthenticationFilter(Order=1)]抛出了一个Exthention,请更新您的答案。好的,但是为什么
var visitCount=Convert.ToInt64(filterContext.HttpContext.Session[“LoggerActivityTracking”].ToString())返回Null,因此会阻止进程,我认为缺少一些内容。你没有完整的实现代码作为参考吗?请,我喜欢你的代码,我想在我的练习中使用。什么是
AuthenticationFilter
?自定义身份验证过滤器?代码?@Kiquenet这是我的另一个身份验证过滤器。我将其从代码中删除,因为此解决方案中不需要它