在 MVC 应用程序中记录用户活动 ASP.NET
本文关键字:活动 ASP NET 用户 记录 MVC 应用程序 | 更新日期: 2023-09-27 18:31:41
>我计划根据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 获取这些值。但是这种方法让我有点困惑,因为我的每个操作都有多余的参数。
是否有任何将值从视图共享到 C# 代码的好方法?
我可以通过以下方式实现这一目标
创建表(名称 - Portal_Logger
和D_MASTER
)
接下来,创建了一个过滤器,该过滤器将跟踪用户的活动,如下所示
记录器操作筛选器.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);
}
}
}
注意:Session["LoggerActivityTracking"]
和Session["LogedUserID"]
数据,我在单独的控制器(AuthController
)操作(ValidateUser
)中初始化,该操作在用户登录应用程序时执行。
下面我使用了一个实用程序类,它将从 RawUrl 中获取网页的确切名称(例如:/Home/MyController
或 /Home/MyController1?id=1&name=chandan
)
下面是我的实用程序类
用户活动实用程序.cs
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;
}
}
}
最后将该属性应用于控制器操作(您要跟踪的操作),如下所示
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存储过程",以获取用户登录详细信息和页面访问摘要详细信息
用户登录详细信息
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
值必须在某个时候由用户或代码设置。 但是,您可以使用 Session
数组来包含这些值。 它们将在登录会话期间保留。
存储到会话
Session["key"] = "data";
以及稍后的代码
var val = Session["key"]; // val now has a value of "data";
我使用的是一个使用反射并将模型转储到字典中的辅助方法,这样您就不会有将值复制到其他地方的问题,所有内容都从一个地方发货"你的模型"
private static Dictionary<string, string> DumpModel(object obt)
{
Type type = obt.GetType();
if (TypeDefinitionIsList(type))
return null;
PropertyInfo[] properties = obt.GetType().GetProperties();
Func<PropertyInfo, string> func = info =>
{
if (info.PropertyType.GetInterface(typeof (ICatalogue<>).FullName) != null)
{
dynamic propertyValue = info.GetValue(obt, null);
if (propertyValue != null)
return string.Format("{{ Id: {0}, Description: {1} }}",
propertyValue.Id,
propertyValue.Description);
return "null";
}
object normalValue = info.GetValue(obt, null);
if (normalValue == null) return "null";
return TypeDefinitionIsList(normalValue.GetType()) ? HelpersMessages.NotSupportedList : normalValue.ToString();
};
return properties.ToDictionary(x => "model-"+x.Name, func);
}
您可以在过滤器属性中使用它
var request = filterContext.HttpContext.Request;
object model = filterContext.Controller.ViewData.Model;
你可以使用类似的东西
DumpModel(model);
使用值记录您需要的码头,我希望这有帮助