ASP .NET Web API:跟踪侦听器:HTTP / 1.1 500内部服务器错误:出了什么问题?

时间:2017-08-07 19:27:54

标签: c# asp.net .net asp.net-mvc nlog

我已经使用.NET一段时间了,但这是我的第一个Web API 2项目。这是一场艰难的斗争,所以请放轻松我。有些关于Web API的内容可能是已知的,明显的或明显的,但是直到你试图找出,例如," {id}&# 34;参数是"魔术"并应尽可能使用。

考虑到这一点,为了帮助我们进一步排除应用程序故障,我尝试使用Trace Listeners和NLog启用日志记录,使用几篇优秀的文章作为指南,包括以下两个:

我正在尝试使用跟踪侦听器和NLog运行ASP .NET Web API服务,以帮助我们在性能较慢的应用程序中记录关键点并为其添加时间戳。

然而,当我从Fiddler测试我的控制器时,我得到一个如下例外:



HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 04 Aug 2017 18:45:11 GMT
Content-Length: 3617

{"Message":"An error has occurred.",
"ExceptionMessage":"Value cannot be null.\r\nParameter name: traceWriter","ExceptionType":"System.ArgumentNullException","StackTrace":"   at System.Web.Http.Tracing.ITraceWriterExtensions.Trace(ITraceWriter traceWriter, HttpRequestMessage request, String category, TraceLevel level, String messageFormat, Object[] messageArguments)\r\n   at PURL_WebMarketing_API.Controllers.VisitorFormController.<GetFormInfo>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---" }
&#13;
&#13;
&#13;

我使用的是Visual Studio 2015,.NET Framework 4.5以及适用于NLog,ASP .NET Web API和ASP .NET Web API跟踪的最新NuGet软件包。

现在代码......

来自App_Start / WebApiConfig.cs:

// Enable tracing
config.EnableSystemDiagnosticsTracing();

// Replace the default trace writer with my own custom handler
config.Services.Replace(typeof(System.Web.Http.Tracing.ITraceWriter), new Utilities.TraceHandler());

在VisitorFormController.cs中:

public class VisitorFormController : ApiController
{
    private IDataAccessRepository _repository;
    private readonly ITraceWriter _tracer;


    public VisitorFormController(IDataAccessRepository repository): base()
    {
        _repository = repository;

        if (Request != null)
        {
            _tracer = Request.GetConfiguration().Services.GetTraceWriter();
        }
    }

[HttpGet]
        [Route("api/VisitorForm/{code}/{pageType}")]
        [EnableCors(origins: "*", headers: "*", methods: "options,get")]
        public async Task<IHttpActionResult> GetFormInfo(string code, string pageType)
        {
            DateTime startTime = DateTime.Now;

            if (string.IsNullOrEmpty(code))
                return BadRequest("Invitation code is required.");

            if (!IsValidPageType(pageType))
                return BadRequest("Valid page types may be 'post', 'info', 'No Code' or blank.");

            if (Request != null)
            {
                string startLogMessage = CustomLogMessageBuilder.GetLogMessage(CustomLogMessageBuilder.StandardStartEventNames.EVENT_TYPE_VISITOR_FORM_REQ_START);
                _tracer.Info(Request, this.ControllerContext.ControllerDescriptor.ControllerType.FullName, startLogMessage);
            }

            // *** Work happens here
            RecipientModel visitorFormInformation =  _repository.GetVisitorFormInformation(code, pageType);
            // ***

            if (visitorFormInformation == null)
                return NotFound();

            if (Request != null)
            {
                string endLogMessage = CustomLogMessageBuilder.GetLogMessage(CustomLogMessageBuilder.StandardEndEventNames.EVENT_TYPE_VISITOR_FORM_REQ_END, startTime);
                _tracer.Info(Request, this.ControllerContext.ControllerDescriptor.ControllerType.FullName, endLogMessage);
            }

            try
            {
                DateTime startLogActivityTime = DateTime.Now;

                if (Request != null)
                {
                    string startLogMessage = CustomLogMessageBuilder.GetLogMessage(CustomLogMessageBuilder.StandardStartEventNames.EVENT_TYPE_UPDATE_VISIT_LOG_FORM_VIEWED_START);
                    _tracer.Info(Request, this.ControllerContext.ControllerDescriptor.ControllerType.FullName, startLogMessage);
                }

                // Log visitor activity, asynchronously
                await _repository.LogActivity(visitorFormInformation.RecipientId, visitorFormInformation.IsCompleted);

                if (Request != null)
                {
                    string endLogMessage = CustomLogMessageBuilder.GetLogMessage(CustomLogMessageBuilder.StandardEndEventNames.EVENT_TYPE_UPDATE_VISIT_LOG_FORM_VIEWED_END, startLogActivityTime);
                    _tracer.Info(Request, this.ControllerContext.ControllerDescriptor.ControllerType.FullName, endLogMessage);
                }
            }
            catch
            {
                return BadRequest("Recipient ID#" + visitorFormInformation.RecipientId.ToString() + " not found.");
            }

            return Ok(visitorFormInformation);
        }

要查看我的自定义跟踪处理程序,请参阅上面发布的Filip Wojcieszyn博客文章。我的版本几乎相同,所以我为了简洁起见省略了它。

如果我在书中做了关于跟踪听众使用的所有内容,那么这可能是我传入的内容吗?在当前状态下,只要禁用跟踪侦听器,该服务就会起作用。

在有人要求之前,我已经在各种浏览器中尝试了这一点。但我很有帮助,非常感谢任何有用的意见和建议。谢谢!

1 个答案:

答案 0 :(得分:2)

问题是HttpContext在控制器的构造函数中尚不可用,这就是Request属性为null的原因,这导致_tracer为null,这导致任何函数调用_tracer投掷ArgumentNullException

我建议你多阅读一下WebApi管道,例如here。它告诉您控制器的构造方式以及请求入站时的情况。

简而言之:解决方案是不将_tracer存储在控制器级别,而是存储在正在执行的操作中,并在每次操作调用时获得“新”跟踪器。

public class VisitorFormController : ApiController
{
    private IDataAccessRepository _repository;

    public VisitorFormController(IDataAccessRepository repository): base()
    {
        _repository = repository;
    }

    [HttpGet]
    [Route("api/VisitorForm/{code}/{pageType}")]
    [EnableCors(origins: "*", headers: "*", methods: "options,get")]
    public async Task<IHttpActionResult> GetFormInfo(string code, string pageType)
    {
       var tracer = Request.GetConfiguration().Services.GetTraceWriter();

       // Use tracer from here on...
    }
}