【问题标题】:Logging Exception using AOP in .netcore web api在.net core web api中使用AOP记录异常
【发布时间】:2018-12-02 16:28:51
【问题描述】:

我正在开发一个 web api 项目,我想使用记录器将 web api 中的所有控制器记录到文件中。

[HttpGet]
    [Route("")]
    public IActionResult GetAllDocumentTempates()
    {
        try
        {
            var document = _doumentTemplate.GetLiteDocumentReportTemplates().ToList();
            var result = Mapper.Map<IEnumerable<LiteDocumentReportTemplateViewModel>>(document);
            return Ok(result);
        }
        catch (Exception ex)
        {
            String msgInnerExAndStackTrace = string.Format("{0}; Inner Ex: {1};  Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
            ExceptionLoggingService.Instance.WriteLog(string.Format("From frmDelivery.ConditionallyPrint():{0}", msgInnerExAndStackTrace));
            return BadRequest();
        }
    }

This is my ExceptionLoggingService.cs: 这是为我处理所有错误并记录到文件的服务

public class ExceptionLoggingService: ActionFilterAttribute
{
    // </ Singleton code
    // private fields
    private readonly FileStream _fileStream;
    private readonly StreamWriter _streamWriter;
    private static ExceptionLoggingService _instance;
    // public property
    public static ExceptionLoggingService Instance
    {
        get
        {
            return _instance ?? (_instance = new ExceptionLoggingService());
        }
    }
    //private constructor
    private ExceptionLoggingService()
    {
        _fileStream = File.OpenWrite(GetExecutionFolder() + "\\EasyAsFallingOffA.log");
        _streamWriter = new StreamWriter(_fileStream);
    }
    // <!-- Singleton code

    public void WriteLog(string message)
    {
        if (!HHSConsts.Logging) return;
        StringBuilder formattedMessage = new StringBuilder();
        formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
        formattedMessage.AppendLine("Message: " + message);
        _streamWriter.WriteLine(formattedMessage.ToString());
        _streamWriter.Flush();
    }
    private string GetExecutionFolder()
    {
        return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

    }
}

这是我的EasyAsFallingOffA.log 文件输出

日期:2018 年 6 月 23 日下午 12:02:24 消息:来自 frmDelivery.ConditionallyPrint():对象引用未设置为对象的实例。;内例:;堆栈跟踪:在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.Domain\Helpers\ModelFactory.cs:line 1170 中的 ProcessFlowManager.Domain.Helpers.ModelFactory.Create(CalendarActivity cal) 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.Infrastructure\LogicImplementations\EfCalendarActivities.cs:line 54 中的 ProcessFlowManager.Infrastructure.LogicImplementations.EfCalendarActivities.GetCalendarActivity(Int32 id) 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.API\Controllers\CalendarController.cs:line 79 中的 ProcessFlowManager.API.Controllers.CalendarController.GetAllGeneratedDcument(Int32 id) 处

上面的所有代码一切正常,但所有这些代码都是使用重言式实现的,因为我在我所有的 try 和 catch 中重复。我是 AOP 的新手,正在寻找一种使用 AOP 执行此操作的方法,这样我就可以在我的控制器中调用它一次。

【问题讨论】:

  • 我需要使用面向方面的编程来实现这一点,但已经尝试了一切但都无济于事,我不想使用第三方
  • 我需要一些建议,请不要介绍第三方,因为它不是免费的

标签: c# asp.net asp.net-web-api2 asp.net-core-webapi


【解决方案1】:

您可以使用此链接开始: Aspect Oriented Programming Using C# and PostSharp

还有这个: Injecting Behaviors Before and After Method Execution

第一层:

1) 使用命名 LoggingAspect 为您的项目添加类

2) OnMethodBoundaryAspect 的继承

3)so 实现 OnEntry,OnSuccess,OnExit,OnException

如下代码:

    [PSerializable]
   public class LoggingAspect : OnMethodBoundaryAspect
   {

     public override void OnEntry(MethodExecutionArgs args)
     {
        Console.WriteLine("The {0} method has been entered.", args.Method.Name);
     }

     public override void OnSuccess(MethodExecutionArgs args)
     {
       Console.WriteLine("The {0} method executed successfully.", args.Method.Name);
     }

     public override void OnExit(MethodExecutionArgs args)
     {
        Console.WriteLine("The {0} method has exited.", args.Method.Name);
     }     

     public override void OnException(MethodExecutionArgs args)
     {
        Console.WriteLine("An exception was thrown in {0}.", args.Method.Name);
     }

    }

  static class Program
  {
      [LoggingAspect]
      static void Main()
      {
         Console.WriteLine("Hello, world.");
      }
   }

输出:

     The Main method has been entered.
     Hello, world.
     The Main method executed successfully.
     The Main method has exited.

【讨论】:

  • 这会将日志添加到文件中
  • 对不起,但这没有帮助我说我不想使用第三方来实现 AOP @Ali Tooshmalani
【解决方案2】:

经过大量改组互联网试图回答我的问题后,我已成功记录所有异常,而无需使用 PostSharp、Log4File、Spring 等第三方库。 使用

ActionFilterAttribute, IExceptionFilter

我能够解决这个问题并使用以下代码记录企业项目的所有异常

public class LatestErrorHandler : ActionFilterAttribute, IExceptionFilter
{
    private const string FILE_NAME = "Exception.log";
    private const string TRACE_FILE = "TraceLog.log";
    public Type _exceptionType;
    FileStream _fileStream;
    StreamWriter _streamWriter;
    IHostingEnvironment host;
    public LatestErrorHandler(Type exceptionType)
    {
       // _fileStream = File.OpenWrite(host.ContentRootPath + "\\wale.log");
        //_streamWriter = new StreamWriter(_fileStream);
        //_fileStream.Close();
        _exceptionType = exceptionType;
    }


    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        using (FileStream fs=new FileStream(TRACE_FILE, FileMode.Append, FileAccess.Write))
        {
            using (BinaryWriter rite=new BinaryWriter(fs))
            {
                if (context.HttpContext.Response==null)
                {
                    string con = "No log";
                    rite.Write(con);
                }
                else
                {
                    Controller exValue = (Controller)context.Controller;
                    ControllerContext control = (ControllerContext)exValue.ControllerContext;
                    ///HttpMethodActionConstraint http = (HttpMethodActionConstraint)control.ActionDescriptor.ActionConstraints.;

                    rite.Write(
                                 "  Date Exception Occurred" + DateTime.Now.ToString() +
                                 "  Route " 
                                 +control.RouteData.DataTokens.Values
                                 +context.RouteData.Routers
                                 //+control.ActionDescriptor.ActionConstraints+ ":"+ http.HttpMethods
                                 + context.RouteData.Values.Keys
                                 + control.ActionDescriptor.ActionName
                                 +context.ActionDescriptor.RouteValues.Values+
                                 "  Parameter"
                                 + context.ActionDescriptor.Parameters 
                                 +context.ActionDescriptor.Properties+
                                 "  Controller" 
                                 + control.ActionDescriptor.ControllerName

                                           );
                }
            }
        }


    }





    public void OnException(ExceptionContext context)
    {
        var cont= context.Exception;
        //var contInner = context.Exception.InnerException;
        using (FileStream fs = new FileStream(FILE_NAME, FileMode.OpenOrCreate, FileAccess.ReadWrite))
        {
            using (BinaryWriter rite = new BinaryWriter(fs))
          {
                // context.Result actionResult = new context.Result();

                if (context.HttpContext.Response == null)
                {
                    string con = "no errroer  ";
                    rite.Write(con);
                }
                else
                {

                    rite.Write(
                        "Date Exception Occurred" + DateTime.Now.ToString() +
                        " Exceptions" + "Message: " + cont.Message +
                        " InnerException" + cont.InnerException +
                        " StackTrace" + cont.StackTrace+
                        "Response" + context.HttpContext.Response.StatusCode
                    );




                }

            }

        }

    }






    public override void OnActionExecuted(ActionExecutedContext context)
    {

        base.OnActionExecuted(context);
        var cont = context.Exception;
        //var contInner = context.Exception.InnerException;
        using (FileStream fs = new FileStream(FILE_NAME, FileMode.Append, FileAccess.Write))
        {
            using (BinaryWriter rite=new BinaryWriter(fs))
            {
                // context.Result actionResult = new context.Result();
               var type =  context.Result.GetType().Name;   //context.Result

                if(type == "BadRequestObjectResult" )
                {

                    BadRequestObjectResult cont2 = (BadRequestObjectResult)context.Result;


                    Exception exValue = (Exception) cont2.Value;
                    if (exValue.InnerException==null)
                    {
                        rite.Write(
                              "\n  Date Exception Occurred  " + DateTime.Now.ToString() +
                              "\n  Exceptions" + "Message: " + cont2.Value +
                             // "\n  InnerException  " + exValue.InnerException +
                              "\n  Message    " + exValue.Message +
                              "\n  StackTrace  " + exValue.StackTrace
                       //"Response" + context.HttpContext.Response.StatusCode
                       );
                    }
                    else
                    {
                        rite.Write(
                               "\n  Date Exception Occurred  " + DateTime.Now.ToString() +
                               "\n  Exceptions" + "Message: " + cont2.Value +
                               "\n  InnerException  " + exValue.InnerException +
                               "\n  Message    " + exValue.Message +
                               "\n  StackTrace  " + exValue.StackTrace
                        //"Response" + context.HttpContext.Response.StatusCode
                        );
                    }


                }






                else
                {
                    // log details without error.





                }

            }

        }

    }



}

在这个类中,我使用面向方面的编程(AOP)成功地将我的所有异常记录到我的所有控制器中的文件中。

 [LatestErrorHandler(typeof(ExceptionContext))]
//[CustomLoggingAttirbute]
[Produces("application/json")]
[Route("api/Calendar")]
public class CalendarController : Controller
{
      ICalendarActivities calendarActivities;

    IHostingEnvironment IHostingEnvironment;

    string projectFolder = "";
    string fileRootPath = "";

    // private string projectRootFolder;
    public CalendarController(ICalendarActivities _calendarActivities)
    {
        calendarActivities = _calendarActivities;
    }

    [HttpGet]
    [Route("")]

    public IActionResult GetAllCalenderReportList()
    {
        try
        {
            var calendars = calendarActivities.GetCalendarActivities();
            var result = AutoMapper.Mapper.Map<IEnumerable<LiteCalendarViewModel>>(calendars);
            return Ok(result);
        }
        catch (Exception ex)

        {
            //string msginnerexandstacktrace = string.Format("{0}; inner ex: {1};  stack trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
            //ExceptionLoggingService.Instance.WriteLog(string.Format("from frmdelivery.conditionallyprint():{0}", msginnerexandstacktrace));
            return BadRequest(ex);
        }
    }

这是我的输出

2018 年 7 月 2 日下午 5:13:18 发生日期异常 ExceptionsMessage:System.NullReferenceException:对象引用未设置为对象的实例。 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.Domain\Helpers\ModelFactory.cs:line 1170 中的 ProcessFlowManager.Domain.Helpers.ModelFactory.Create(CalendarActivity cal) 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.Infrastructure\LogicImplementations\EfCalendarActivities.cs:line 48 中的 ProcessFlowManager.Infrastructure.LogicImplementations.EfCalendarActivities.GetCalendarActivity(Int32 id) 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.API\Controllers\CalendarController.cs:line 83 中的 ProcessFlowManager.API.Controllers.CalendarController.GetAllGeneratedDcument(Int32 id) 内部异常
消息对象引用未设置为对象的实例。 StackTrace 在 C:\Users\BABATUNDE\Documents\Visual Studio 2017\Projects\pcm-netcore\ProcessFlowManager.Domain\Helpers\ModelFactory.cs:line 1170 中 ProcessFlowManager.Domain.Helpers.ModelFactory.Create(CalendarActivity cal)

【讨论】:

  • 就我而言,当我根本不处理异常时,这种方法非常有效。如果我在方法中有一个 try-catch 块,那么通过属性指定的错误处理程序似乎没有反应。
猜你喜欢
  • 2019-08-30
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2017-11-22
  • 1970-01-01
  • 2021-04-21
  • 2021-02-14
  • 1970-01-01
相关资源
最近更新 更多