1

シナリオ

パートナーが公開した Web サービスを使用しています。.NET プロキシ クライアントを実装しています。Web メソッド呼び出しに関連する XML をシリアライズしたいと考えています。目的は、さらなる処理/再処理/ロギングのためにリクエストの詳細を保存することです。

各パラメーターがフィールドに対応するようにテーブルを形成できます。ただし、この方法では、テーブルは Web メソッド シグネチャに厳密に関連付けられます。代わりに、SOAP 要求の XML 本体を保持する一般的な WebServiceClientRequest テーブルを作成したいと考えています。

最終的には、各パラメーターをマップする関連テーブルをいつでも追加できます。

質問

SOAP リクエストの XML コンテンツをシリアル化する方法はありますか?

4

1 に答える 1

2

方法は確かにあります。MSDN の記事「ウォークスルー: SOAP 拡張機能を使用した SOAP メッセージの変更」で説明されているように、SOAP 拡張機能を使用することをお勧めします。

次に、カスタム DAL マネージャーを使用して SOAP メッセージを DB に格納しました。

詳細はこちら。

public class SOAPTraceDB : SoapExtension
{
    private Stream oldStream;
    private Stream newStream;
    private string ConnectionString;

    private Int32 RequestId;

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

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }

    // The SOAP extension was configured to run using a configuration file
    // instead of an attribute applied to a specific XML Web service
    // method.
    public override object GetInitializer(Type WebServiceType)
    {
        // Return a db table to log the trace information to, based on the type.
        return MyConfigurationManager.GetAppSetting<string>("SOAPTraceLoggerConnectionString");

    }

    public override void Initialize(object initializer)
    {
        ConnectionString = (string)initializer;
    }

    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                WriteRequest(message);
                break;
            case SoapMessageStage.BeforeDeserialize:
                WriteResponse(message);
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
            default:
                throw new Exception("invalid stage");
        }
    }

    public void WriteRequest(SoapMessage message)
    {
        newStream.Position = 0;
        Stream s = new MemoryStream();

        Copy(newStream, s);
        RequestId = MyDALStaticManager.WriteMessage(DateTime.Now, SOAPMessageType.request, StreamToString(s));
        s.Close();
        newStream.Position = 0;
        Copy(newStream, oldStream);

    }

    public void WriteResponse(SoapMessage message)
    {
        Stream s = new MemoryStream();

        Copy(oldStream, newStream);
        newStream.Position = 0;
        Copy(newStream, s);
        MyDALStaticManager.WriteMessage(DateTime.Now, SOAPMessageType.response, StreamToString(s), RequestId);
        newStream.Position = 0;
        s.Close();
    }

    private string StreamToString(Stream s)
    {
        string res = string.Empty;
        s.Position = 0;

        StreamReader r = new StreamReader(s);

        //SQL Server accept only utf-16 encoding. Is there a better way to set up the stream encoding? utf-16 is not featured among the System.Text.Encoding
        res = r.ReadToEnd().Replace("encoding=\"utf-8\"", "encoding=\"utf-16\"");
        r.Close();

        return res;
    }

    private void Copy(Stream from, Stream to)
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);

        string str = reader.ReadToEnd();

        str = XmlUtils.FormatXml(str);

        writer.WriteLine(str);
        writer.Flush();
    }
}
于 2013-07-10T17:14:23.377 に答える