考虑将传入的SOAP请求记录到ASP.NET ASMX Web服务的要求。任务是捕获发送到Web服务的原始XML。
需要记录传入消息以进行调试检查。应用程序已经有自己的日志库,因此理想的用法是这样的:
//string or XML, it doesn't matter.
string incomingSoapRequest = GetSoapRequest();
Logger.LogMessage(incomingSoapRequest);
答案 0 :(得分:19)
捕获原始邮件的一种方法是使用SoapExtensions。
SoapExtensions的替代方法是实现IHttpModule并在输入流时抓取输入流。
public class LogModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += this.OnBegin;
}
private void OnBegin(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext context = app.Context;
byte[] buffer = new byte[context.Request.InputStream.Length];
context.Request.InputStream.Read(buffer, 0, buffer.Length);
context.Request.InputStream.Position = 0;
string soapMessage = Encoding.ASCII.GetString(buffer);
// Do something with soapMessage
}
public void Dispose()
{
throw new NotImplementedException();
}
}
答案 1 :(得分:18)
您也可以通过将代码放在Global.asax.cs
中来实现protected void Application_BeginRequest(object sender, EventArgs e)
{
// Create byte array to hold request bytes
byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];
// Read entire request inputstream
HttpContext.Current.Request.InputStream.Read(inputStream, 0, inputStream.Length);
//Set stream back to beginning
HttpContext.Current.Request.InputStream.Position = 0;
//Get XML request
string requestString = ASCIIEncoding.ASCII.GetString(inputStream);
}
我在我的网络服务中有一个实用工具方法,用于在发生某些事情时捕获请求,我不期望这是一个未处理的异常。
/// <summary>
/// Captures raw XML request and writes to FailedSubmission folder.
/// </summary>
internal static void CaptureRequest()
{
const string procName = "CaptureRequest";
try
{
log.WarnFormat("{0} - Writing XML request to FailedSubmission folder", procName);
byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];
//Get current stream position so we can set it back to that after logging
Int64 currentStreamPosition = HttpContext.Current.Request.InputStream.Position;
HttpContext.Current.Request.InputStream.Position = 0;
HttpContext.Current.Request.InputStream.Read(inputStream, 0, HttpContext.Current.Request.ContentLength);
//Set back stream position to original position
HttpContext.Current.Request.InputStream.Position = currentStreamPosition;
string xml = ASCIIEncoding.ASCII.GetString(inputStream);
string fileName = Guid.NewGuid().ToString() + ".xml";
log.WarnFormat("{0} - Request being written to filename: {1}", procName, fileName);
File.WriteAllText(Configuration.FailedSubmissionsFolder + fileName, xml);
}
catch
{
}
}
然后在web.config中我存储了几个AppSetting值,这些值定义了我想用来捕获请求的级别。
<!-- true/false - If true will write to an XML file the raw request when any Unhandled exception occurrs -->
<add key="CaptureRequestOnUnhandledException" value="true"/>
<!-- true/false - If true will write to an XML file the raw request when any type of error is returned to the client-->
<add key="CaptureRequestOnAllFailures" value="false"/>
<!-- true/false - If true will write to an XML file the raw request for every request to the web service -->
<add key="CaptureAllRequests" value="false"/>
然后在我的Application_BeginRequest中,我对其进行了修改。请注意,Configuration是我创建的静态类,用于从web.config和其他区域读取属性。
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(Configuration.CaptureAllRequests)
{
Utility.CaptureRequest();
}
}
答案 2 :(得分:12)
您知道实际需要创建HttpModule
权利吗?
您还可以在asmx Request.InputStream
中阅读WebMethod
的内容。
这是an article I wrote on this approach。
代码如下:
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace SoapRequestEcho
{
[WebService(
Namespace = "http://soap.request.echo.com/",
Name = "SoapRequestEcho")]
public class EchoWebService : WebService
{
[WebMethod(Description = "Echo Soap Request")]
public XmlDocument EchoSoapRequest(int input)
{
// Initialize soap request XML
XmlDocument xmlSoapRequest = new XmlDocument();
// Get raw request body
Stream receiveStream = HttpContext.Current.Request.InputStream;
// Move to beginning of input stream and read
receiveStream.Position = 0;
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
// Load into XML document
xmlSoapRequest.Load(readStream);
}
// Return
return xmlSoapRequest;
}
}
}
答案 3 :(得分:-2)
没有简单的方法可以做到这一点。您必须实施SoapExtension。上一个链接的示例显示了可用于记录数据的扩展名。
如果您一直在使用WCF,那么您只需设置配置即可生成消息日志。
根据Steven de Salas,您可以使用webmethod中的Request.InputStream
属性。我没试过这个,但他说它有效。
我想用http和https测试它,并且同时运行和不运行其他SoapExtensions。这些可能会影响InputStream
设置的流类型。例如,某些流无法搜索,这可能会使您在数据结束后定位流,并且无法移动到开头。