我想在我的网站上实现一个日志机制,我希望做一些基本的用户操作日志记录。我不想记录他们点击的每一个按钮,但我确实希望记录他们所做的操作,这些操作会进行更改。
是否有任何库或文章/教程可以帮助我为我的asp.net站点实现一个良好而高效的日志机制。我不确定MVC5中是否有任何用于日志记录的更改,因为我知道用户身份验证和授权已经将相当大的数量从4更改为5。
我确信有一个动态库可以在许多不同的情况下工作。
很高兴拥有:
我正在考虑创建一个自定义过滤器或属性,然后记录suers的操作,但这只是我的想法,我想问一下标准/行业的方法是什么。
发布于 2014-04-14 12:22:28
没有行业标准。我使用了过滤器或者重写了基类上的"onActionExecuting“方法来记录控制器/动作事件。
编辑::
试图提供更多的帮助,但这是非常模糊的。如果你担心错误和诸如此类的事情,请使用elmah。对于其他日志记录,请使用Nlog或Log4Net。
如果您试图进行额外的日志记录,如审计之类的,您可以使用任何组合,或定制的东西。在我的站点中,我创建了一个表,通过创建一个类似于这样的对象来存储站点上的每一次单击:
public class audit
{
public int ID { get; set; }
public DateTime AuditDate { get; set; }
public string ControllerName { get; set; }
public string ActionName { get; set; }
public Dictionary<string, object> values
}
在我的基本构造函数中,我重写了OnActionExecuting事件:
protected override void OnActionExecuting(ActionExecutingContext ctx)
{
checkForLogging(ctx);
//do not omit this line
base.OnActionExecuting(ctx);
}
假设我想使用我的新审计对象记录所有Get请求
private void checkForLogging(ActionExecutingContext ctx)
{
//we leave logging of posts up to the actual methods because they're more complex...
if (ctx.HttpContext.Request.RequestType == "GET")
{
logging(ctx.ActionDescriptor.ActionName, ctx.ActionDescriptor.ControllerDescriptor.ControllerName, ctx.ActionParameters);
}
}
这就是我需要的全部信息,我需要用操作名称、控制器名称和传递给方法的所有参数填充日志对象。您可以将其保存到db、日志文件或任何您真正想要的东西中。
关键是这是一件很重要的事情。这只是一种方法,它可能对你有帮助,也可能对你没有帮助。也许更多地定义一下你到底想要记录什么,以及什么时候你想要记录?
您可以创建一个自定义属性并使用它来装饰方法,然后在OnActionExecuting方法触发时检查该属性是否存在。你可以得到过滤器,如果有,并从中读取,并使用它来驱动你的日志记录,如果你想.
发布于 2015-02-05 19:15:07
也许这个例子会有帮助。我对日志记录的关注集中在创建、编辑、删除操作中。
我使用的是MVC 5代码--第一个EF 6.1 (VS 2013),在本例中,我指的是一个名为"WorkFlow“的实体的创建操作。
实际上,我从SSRS中查看了这些日志,但是您可以为WriteUsageLog添加一个控制器和视图,然后从MVC应用程序中查看它们。
- User Name from Active Directory
- The DateTime that the log record is being created
- The computer name
- And a Note that consists of the values for all the entity properties
/模型/WriteUsageLog.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MileageReimbursement.Models
{
public class WriteUsageLog
{
public WriteUsageLog()
{
this.DateTimeCreated = DateTime.Now; // auto-populates DateTimeCreated field
}
[Key]
public int WriteUsageLogID { get; set; }
[Column(TypeName = "nvarchar(max)")]
public string Note { get; set; }
public string UserLogIn { get; set; }
public string ComputerName { get; set; }
public DateTime DateTimeCreated { get; private set; } //private set to for auto-populates DateTimeCreated field
}
}
/控制器/控制器
using System.Linq;
using System.Web.Mvc;
using MileageReimbursement.Models;
//These partials are to avoid be deleted and rebuilt when I use the wizard to create Controllers
namespace MileageReimbursement.Controllers
{
public partial class WorkFlowController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "whatever")] WorkFlow workFlow)
{
...
if (ModelState.IsValid)
{
db.WorkFlows.Add(workFlow);
db.SaveChanges();
//===================================================================================================================
string sX = workFlow.GetStringWith_RecordProperties();
//===================================================================================================================
var logRecord = new WriteUsageLog();
logRecord.Note = "New WorkFlow Record Added - " + sX;
logRecord.UserLogIn = General_ActiveDirectory_Extensions.fn_sUser();
string IP = Request.UserHostName;
logRecord.ComputerName = General_functions.fn_ComputerName(IP);
db.WriteUsageLogs.Add(logRecord);
db.SaveChanges();
//===================================================================================================================
return RedirectToAction("Index");
}
else // OR the user is directed back to the validation error messages and given an opportunity to correct them
{
...
return View(workFlow); //This sends the user back to the CREATE view to deal with their errors
}
}
}
}
/控制器/控制器扩展。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace MileageReimbursement.Controllers
{
public static class General_ActiveDirectory_Extensions
{
public static string fn_sUser()
{
char cX = '\\';
string sUser = General_functions.fn_ReturnPortionOfStringAfterLastOccuranceOfACharacter(HttpContext.Current.User.Identity.Name, cX);
return sUser; //returns just the short logon name Example for 'accessiicarewnc\ggarson', it returns 'ggarson'
}
} //General_ActiveDirectory_Extensions
public static class General_Object_Extensions
{
public static string GetStringWith_RecordProperties(this object Record)
{
string sX = null;
Dictionary<string, object> _record = GetDictionary_WithPropertiesForOneRecord(Record);
int iPropertyCounter = 0;
foreach (var KeyValuePair in _record)
{
iPropertyCounter += 1;
object thePropertyValue = _record[KeyValuePair.Key];
if (thePropertyValue != null)
{
sX = sX + iPropertyCounter + ") Property: {" + KeyValuePair.Key + "} = [" + thePropertyValue + "] \r\n";
}
else
{
sX = sX + iPropertyCounter + ") Property: {" + KeyValuePair.Key + "} = [{NULL}] \r\n";
}
}
return sX;
}
public static Dictionary<string, object> GetDictionary_WithPropertiesForOneRecord(object atype)
{
if (atype == null) return new Dictionary<string, object>();
Type t = atype.GetType();
PropertyInfo[] props = t.GetProperties();
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (PropertyInfo prp in props)
{
object value = prp.GetValue(atype, new object[] { });
dict.Add(prp.Name, value);
}
return dict;
}
} //General_Object_Extensions
public static class General_functions
{
public static string fn_ComputerName(string IP)
{
//USAGE
//From: http://stackoverflow.com/questions/1444592/determine-clients-computer-name
//string IP = Request.UserHostName;
//string compName = CompNameHelper.DetermineCompName(IP);
IPAddress myIP = IPAddress.Parse(IP);
IPHostEntry GetIPHost = Dns.GetHostEntry(myIP);
List<string> compName = GetIPHost.HostName.ToString().Split('.').ToList();
return compName.First();
}
static public string fn_ReturnPortionOfStringAfterLastOccuranceOfACharacter(string strInput, char cBreakCharacter)
{
// NOTE: for path backslash "/", set cBreakCharacter = '\\'
string strX = null;
//1] how long is the string
int iStrLenth = strInput.Length;
//2] How far from the end does the last occurance of the character occur
int iLenthFromTheLeftOfTheLastOccurance = strInput.LastIndexOf(cBreakCharacter);
int iLenthFromTheRightToUse = 0;
iLenthFromTheRightToUse = iStrLenth - iLenthFromTheLeftOfTheLastOccurance;
//3] Get the Portion of the string, that occurs after the last occurance of the character
strX = fn_ReturnLastXLettersOfString(iLenthFromTheRightToUse, strInput);
return strX;
}
static private string fn_ReturnLastXLettersOfString(int iNoOfCharToReturn, string strIn)
{
int iLenth = 0;
string strX = null;
int iNoOfCharacters = iNoOfCharToReturn;
iLenth = strIn.Length;
if (iLenth >= iNoOfCharacters)
{
strX = strIn.Substring(iLenth - iNoOfCharacters + 1);
}
else
{
strX = strIn;
}
return strX;
}
} //General_functions
}
发布于 2014-09-04 14:40:22
我同意Log4Net和NLog似乎是我作为成员的不同项目中最常用的两种产品。
如果您正在寻找一个很好的工具,您可以使用它来进行日志记录、错误处理和其他任何有益于AOP的操作,那么我强烈推荐PostSharp (http://www.postsharp.net/)。您可以集中设置日志记录/错误处理,然后只需修饰方法。它是一个有良好文档和支持的产品。他们有一个社区许可证,这是免费的--对个人来说是免费的。他们也有专业的和最终的版本的产品,这将是更有意义的,如果你使用它作为一个团队。
我在PostSharp不工作:-)我过去就用过它,而且真的很喜欢它。
https://stackoverflow.com/questions/23053875
复制相似问题