捕获SOAP请求到ASP.NET ASMX Web服务

p.c*_*ell 30 asp.net soap web-services asmx

考虑将传入的SOAP请求记录到ASP.NET ASMX Web服务的要求.任务是捕获发送到Web服务的原始XML.

需要记录传入消息以进行调试检查.该应用程序已经有自己的日志库,因此理想的用法是这样的:

//string or XML, it doesn't matter.
string incomingSoapRequest = GetSoapRequest();

Logger.LogMessage(incomingSoapRequest);
Run Code Online (Sandbox Code Playgroud)
  • 是否有任何简单的解决方案来捕获传入SOAP请求的原始XML?
  • 您将处理哪些事件来访问此对象和相关属性?
  • 无论如何IIS是否可以捕获传入的请求并推送到日志?

niv*_*lam 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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Jim*_*ott 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);

}
Run Code Online (Sandbox Code Playgroud)

我在我的Web服务中有一个Utility方法,用于在发生某些事情时捕获请求,我并不期望这是一个未处理的异常.

    /// <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
        {
        }

    }
Run Code Online (Sandbox Code Playgroud)

然后在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"/>
Run Code Online (Sandbox Code Playgroud)

然后在我的Application_BeginRequest中,我将其修改为如此.请注意,Configuration是我创建的静态类,用于从web.config和其他区域读取属性.

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

        if(Configuration.CaptureAllRequests)
        {
            Utility.CaptureRequest();
        }
    }
Run Code Online (Sandbox Code Playgroud)


Ste*_*las 12

你知道你真的不需要创造一个HttpModule权利吗?

您还可以Request.InputStream在asmx中读取from 的内容WebMethod.

这是我在这种方法上写的一篇文章.

代码如下:

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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)