将SOAP请求捕获到ASP.NET ASMX Web服务
考虑将传入的SOAP请求logging到ASP.NET ASMX Web服务的要求。 其任务是捕获发送到Web服务的原始XML。
传入的消息需要logging下来进行debugging检查。 应用程序已经有了自己的日志库,所以理想的用法是这样的:
//string or XML, it doesn't matter. string incomingSoapRequest = GetSoapRequest(); Logger.LogMessage(incomingSoapRequest);
- 有没有简单的解决scheme来捕获传入的SOAP请求的原始XML?
- 你会处理哪些事件来访问这个对象和相关的属性?
- 反正有IIS可以捕获传入的请求并推送到日志?
捕获原始消息的一种方法是使用SoapExtensions 。
SoapExtensions的一个替代方法是实现IHttpModule,并在inputstream中获取inputstream。
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(); } }
您也可以通过将代码放在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); }
我在我的web服务中有一个实用程序方法,当我不期待像未处理的exception那样的事情发生时,我用它来捕获请求。
/// <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(); } }
你知道你实际上不需要创build一个HttpModule
吗?
您也可以从asmx WebMethod
读取Request.InputStream
的内容。
这里是一篇关于这个方法的文章 。
代码如下:
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; } } }
有没有简单的方法来做到这一点。 你将不得不实施一个SoapExtension 。 上一个链接中的示例显示了可用于logging数据的扩展。
如果你一直在使用WCF,那么你可以简单地设置configuration来产生消息日志。
根据Steven de Salas的说法,您可以使用webmethod中的Request.InputStream
属性。 我还没有尝试过,但他说这是有效的。
我想用http和httpstesting这个,并且同时运行和不运行其他的SoapExtensions。 这些东西可能会影响InputStream
所设置的streamtypes。 例如,某些数据stream无法查找,例如,可能会在数据结束后放置一个数据stream,并且无法移动到起点。
我知道我已经4年了,但现在我们还有小提琴手也这样做。