0

私のソリューションでは、3つのプロジェクトがあります。1つはWebサービス(ASMX)で、もう1つはWebサービスを呼び出しているところからのWinフォームアプリです。クラスがSoapExtensionクラスを拡張するように設計されている別のクラスライブラリ。

私の目的は、WinフォームアプリからWebサービスを呼び出しているときに応答と要求のxmlをキャプチャすることです。xmlをキャプチャしようとすると、オブジェクト参照が設定されていないというエラーが発生します。

これが私のクラスライブラリのソースコードです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Net;
using System.Xml;

namespace SoapLogger
{
public class TraceExtension : SoapExtension
{
    private Stream oldStream;
    private Stream newStream;

    private static XmlDocument xmlRequest;
    /// <summary>
    /// Gets the outgoing XML request sent to PayPal
    /// </summary>
    public static XmlDocument XmlRequest
    {
        get { return xmlRequest; }
    }

    private static XmlDocument xmlResponse;
    /// <summary>
    /// Gets the incoming XML response sent from PayPal
    /// </summary>
    public static XmlDocument XmlResponse
    {
        get { return xmlResponse; }
    }

    /// <summary>
    /// Save the Stream representing the SOAP request
    /// or SOAP response into a local memory buffer.
    /// </summary>
    /// <param name="stream">
    /// <returns></returns>
    public override Stream ChainStream(Stream stream)
    {
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    /// <summary>
    /// If the SoapMessageStage is such that the SoapRequest or
    /// SoapResponse is still in the SOAP format to be sent or received,
    /// save it to the xmlRequest or xmlResponse property.
    /// </summary>
    /// <param name="message">
    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                xmlRequest = GetSoapEnvelope(newStream);
                CopyStream(newStream, oldStream);
                break;
            case SoapMessageStage.BeforeDeserialize:
                CopyStream(oldStream, newStream);
                xmlResponse = GetSoapEnvelope(newStream);
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
        }
    }

    /// <summary>
    /// Returns the XML representation of the Soap Envelope in the supplied stream.
    /// Resets the position of stream to zero.
    /// </summary>
    /// <param name="stream">
    /// <returns></returns>
    private XmlDocument GetSoapEnvelope(Stream stream)
    {
        XmlDocument xml = new XmlDocument();
        stream.Position = 0;
        StreamReader reader = new StreamReader(stream);
        xml.LoadXml(reader.ReadToEnd());
        stream.Position = 0;
        return xml;
    }

    /// <summary>
    /// Copies a stream.
    /// </summary>
    /// <param name="from">
    /// <param name="to">
    private void CopyStream(Stream from, Stream to)
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
    }
    #region NoOp
    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="methodInfo">
    /// <param name="attribute">
    /// <returns></returns>
    public override object GetInitializer(LogicalMethodInfo methodInfo,
        SoapExtensionAttribute attribute)
    {
        return null;
    }

    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="WebServiceType">
    /// <returns></returns>
    public override object GetInitializer(Type WebServiceType)
    {
        return null;
    }

    /// <summary>
    /// Included only because it must be implemented.
    /// </summary>
    /// <param name="initializer">
    public override void Initialize(object initializer)
    {
    }
    #endregion NoOp
}
}

ここでは、winアプリからWebサービスを呼び出す方法を示します

    private void button1_Click(object sender, EventArgs e)
    {

        using (ServiceRef.TestServiceSoapClient oService = new ServiceRef.TestServiceSoapClient())
        {
            textBox1.Text = oService.HelloWorld("Sudip");
            var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
            var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
        }
    }

この2行は、オブジェクト参照エラーを示しています

            var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
            var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;

エラーが発生する理由がわかりませんでした。

Win形式のアプリにはapp.configが1つあり、クラスライブラリアセンブリを登録してxmlをキャプチャします。これが私のapp.configの詳細です

<?xml version="1.0"?>
<configuration>
<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="TestServiceSoap"/>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:6804/Service1.asmx" binding="basicHttpBinding" bindingConfiguration="TestServiceSoap" contract="ServiceRef.TestServiceSoap" name="TestServiceSoap"/>
    </client>
</system.serviceModel>

<system.web>
<compilation debug="true" targetFramework="4.0" />
<webServices>
  <soapExtensionTypes>
    <add type="SoapLogger.TraceExtension,SoapLogger" priority="1" group="0" />
  </soapExtensionTypes>
</webServices>
</system.web>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup>    
</configuration>

リクエスト/レスポンスxmlをキャプチャする方法を知るためにグーグルを検索すると、この種の多くの記事が表示されます。私は多くをフォローしましたが、何も機能しません。

私が仕事を成し遂げるためにたどったこのURLhttp ://jramirezdev.net/blog/c-tip-capturar-los-mensajes-soap-de-un-servicio-asmx-que-hemos-referenciado

どんな間違いをしているのかはっきりしていません。クラスライブラリメソッドのすべてのメソッドにブレークポイントを設定しましたが、Webサービス呼び出し時に、クラスライブラリでメソッドが実行されませんでした。私はwireshark、fiddlerのようなツールを使用して要求/応答xmlをキャプチャするのではなく、プログラムで同じことを実行したいと考えています。

だから私の間違いを教えてください。オブジェクト参照が設定されていないというエラーが発生するのはなぜですか。私のコードを見るか、URLリンクにアクセスして、私のアプローチの何が問題になっているのか教えてください。

4

0 に答える 0