首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Asp.net MVC 5项目中的事件和错误记录

Asp.net MVC 5项目中的事件和错误记录
EN

Stack Overflow用户
提问于 2014-04-14 07:01:28
回答 3查看 11.7K关注 0票数 2

我想在我的网站上实现一个日志机制,我希望做一些基本的用户操作日志记录。我不想记录他们点击的每一个按钮,但我确实希望记录他们所做的操作,这些操作会进行更改。

是否有任何库或文章/教程可以帮助我为我的asp.net站点实现一个良好而高效的日志机制。我不确定MVC5中是否有任何用于日志记录的更改,因为我知道用户身份验证和授权已经将相当大的数量从4更改为5。

我确信有一个动态库可以在许多不同的情况下工作。

很高兴拥有:

  • 异步能力
  • 可扩展
  • 简单易用

我正在考虑创建一个自定义过滤器或属性,然后记录suers的操作,但这只是我的想法,我想问一下标准/行业的方法是什么。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-14 12:22:28

没有行业标准。我使用了过滤器或者重写了基类上的"onActionExecuting“方法来记录控制器/动作事件。

编辑::

试图提供更多的帮助,但这是非常模糊的。如果你担心错误和诸如此类的事情,请使用elmah。对于其他日志记录,请使用Nlog或Log4Net。

如果您试图进行额外的日志记录,如审计之类的,您可以使用任何组合,或定制的东西。在我的站点中,我创建了一个表,通过创建一个类似于这样的对象来存储站点上的每一次单击:

代码语言:javascript
运行
复制
    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事件:

代码语言:javascript
运行
复制
    protected override void OnActionExecuting(ActionExecutingContext ctx)
    {
        checkForLogging(ctx);

        //do not omit this line
        base.OnActionExecuting(ctx);
    }

假设我想使用我的新审计对象记录所有Get请求

代码语言:javascript
运行
复制
  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方法触发时检查该属性是否存在。你可以得到过滤器,如果有,并从中读取,并使用它来驱动你的日志记录,如果你想.

票数 5
EN

Stack Overflow用户

发布于 2015-02-05 19:15:07

也许这个例子会有帮助。我对日志记录的关注集中在创建、编辑、删除操作中。

我使用的是MVC 5代码--第一个EF 6.1 (VS 2013),在本例中,我指的是一个名为"WorkFlow“的实体的创建操作。

实际上,我从SSRS中查看了这些日志,但是您可以为WriteUsageLog添加一个控制器和视图,然后从MVC应用程序中查看它们。

  1. 模型:创建一个名为"WriteUsageLog“的模型实体,该实体将保存日志记录
  2. 控制器:将" create“操作的HttpPost重载提取或重构为一个名为" WorkFlowController”的部分类(这些部分是为了避免在使用向导创建控制器时被删除和重建)
  3. 控制器文件夹中的其他类:然后在一个名为"General_Object_Extensions“和"General_ActiveDirectory_Extensions”的类中需要一些助手函数(注意:这些不是真正的‘扩展’)
  4. 将以下行添加到DBContext中: 公共DbSet WriteUsageLogs { get;set;} 这个例子的优点是:
  5. 我现将下列资料记录在案:

代码语言:javascript
运行
复制
- 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

  1. 我正在将日志记录在一个表中,我可以使用MVC控制器访问它,或者最好从Server报表服务器访问它。我可以监视我所有的MVC应用程序

/模型/WriteUsageLog.cs

代码语言:javascript
运行
复制
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

    }
}

/控制器/控制器

代码语言:javascript
运行
复制
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
            }
        }
    }
}

/控制器/控制器扩展。

代码语言:javascript
运行
复制
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
    }
票数 2
EN

Stack Overflow用户

发布于 2014-09-04 14:40:22

我同意Log4Net和NLog似乎是我作为成员的不同项目中最常用的两种产品。

如果您正在寻找一个很好的工具,您可以使用它来进行日志记录、错误处理和其他任何有益于AOP的操作,那么我强烈推荐PostSharp (http://www.postsharp.net/)。您可以集中设置日志记录/错误处理,然后只需修饰方法。它是一个有良好文档和支持的产品。他们有一个社区许可证,这是免费的--对个人来说是免费的。他们也有专业的和最终的版本的产品,这将是更有意义的,如果你使用它作为一个团队。

我在PostSharp不工作:-)我过去就用过它,而且真的很喜欢它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23053875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档