在exception期间捕获原始HTTP POST数据

我有一个托管在IIS / ASP.NET中的WCF服务,它接受序列化对象的HTTP Post( 不是表单post )。

如果客户端发送格式错误的请求(例如,他们没有正确序列化对象),我想记录发送的消息。

我们已经在使用ELMAH捕获未处理的exception,因此只需附加发布数据就是最简单的选择。

我可以在exception期间获取当前的HttpContext,但是这只包含HTTP标头信息。

我的问题是:有没有办法捕获原始HTTP POST请求正文? 或者,失败 – 捕获导致错误的输入的更好方法(没有反向代理)?

编辑:只是为了澄清,始终运行数据包级捕获并不合适。 我正在寻找一个可以部署到生产服务器的解决方案,它将拥有我们无法控制的客户端或监控能力。

编辑#2:建议访问Request.InputStream – 如果您在WCF已从流中读取请求后尝试读取,则此操作无效。

一个示例代码,以了解我是如何尝试使用它的。

StringBuilder log = new StringBuilder(); var request = HttpContext.Current.Request; if (request.InputStream != null) { log.AppendLine(string.Format("request.InputStream.Position = \"{0}\"", request.InputStream.Position)); if (request.InputStream.Position != 0) { request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); } using (StreamReader sr = new StreamReader(request.InputStream)) { log.AppendLine(string.Format("Original Input: \"{0}\"", sr.ReadToEnd())); } } else { log.AppendLine("request.Inputstream = null"); } log.ToString(); 

log.ToString()的输出是:

     request.InputStream.Position =“0”
    原始输入:“”

当它到达您的服务时,请求将被处理并且不可用。

但是……你可以附上一个消息检查员 。 消息检查器允许您在消息到达操作实现之前调整消息。 您可以创建消息的缓冲副本,并将其复制到OperationContext.Current中。

当然是丑陋的黑客,它将意味着内存开销,因为现在每个请求都会浮动两个消息副本。

你看过System.Web.Request.InputStream属性了吗? 它应该具有你想要的。

如何“回滚”InputStream属性。

  if (Request.InputStream.Position != 0) { Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); } 

您应该考虑的另一个选项是在BeginRequest事件上使用HTTPModule捕获此信息。 数据应该在BeginRequest事件中,因为我不相信WCF会在PostAuthenticateEvent之后获取请求。

从ASP.NET(IIS下的ASP Web服务)下面的代码可以帮助:

 if (request.InputStream.Position != 0) { request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); } 

WCF可能不同(也就是在读取后调用InputStream)

使用提琴手。 免于MS。 效果很好。