web-dev-qa-db-ja.com

SOAP= ASP.NET ASMX Webサービスへのリクエストのキャプチャ

ASP.NET ASMX Webサービスへの着信SOAP要求をログに記録する要件を考慮してください。タスクは、Webサービスに送信される未加工のXMLをキャプチャすることです。

デバッグ検査のために、着信メッセージをログに記録する必要があります。アプリケーションには既に独自のロギングライブラリが使用されているため、理想的な使用方法は次のようになります。

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

Logger.LogMessage(incomingSoapRequest);
  • 着信SOAP=リクエストの生のXMLをキャプチャする簡単なソリューションはありますか?
  • このオブジェクトと関連するプロパティにアクセスするには、どのイベントを処理しますか?
  • とにかくIISは着信リクエストをキャプチャしてログにプッシュできますか?
30
p.campbell

生のメッセージをキャプチャする1つの方法は、 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();
    }
}
19
nivlam

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サービスには、未処理の例外のような予期しない何かが発生したときにリクエストをキャプチャするために使用するユーティリティメソッドがあります。

    /// <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();
        }
    }
18
Jim Scott

あなたは実際にいけないことを知っている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;
    }
  }
}
12
Steven de Salas