8

IClientMessageInspectorアプリケーションで発信 Web サービス呼び出しを「インターセプト」するために実装しました。BeforeSendRequestandの中から呼び出されている操作を見つけることは可能AfterReceiveReplyですか?

ここに同様の質問があります。WCF Message Inspector 内で呼び出された操作名を取得するにはどうすればよいですか。これはサーバー側 (要求を受信する側) 用です。私は似たようなことをしようとしました、例えば

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        var v = OperationContext.Current.OutgoingMessageProperties["HttpOperationName"];
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        var v = OperationContext.Current.OutgoingMessageProperties["HttpOperationName"];
    }

しかし、送信リクエスト中に OperationContext.Current が null のように見えるため、これを使用できません。それを取得する方法はありますか?それをきれいに行う方法はありますか(反対に、SOAP xmlを解析します)?

4

2 に答える 2

5

IParameterInspectorでこれを行う方法を尋ねたコメントから。操作名は、Before/AfterCall メソッドの一部です。

どのインスペクターを使用するかについての私のコメントに追加するだけです。Carlos Figueira のブログから:

このシリーズの前回の投稿で説明したメッセージ インスペクターを使用すると、WCF スタックを通過するメッセージを完全に制御できます。これらは非常に強力ですが、Message オブジェクトの処理方法を知っておく必要があり、これは最も望ましいプログラミング方法ではありません。WCF のサービス モデルが、厳密に型指定された操作 (つまり、Nice プリミティブ型とユーザー定義型を使用) の観点からサービスを定義できるようにすることで、すべてのメッセージング フレームワークを隠している場合、要求/応答をインターセプトする方法が必要です。これらのパラメーターを受信メッセージから (または送信メッセージにパッケージ化される前に) 抽出する処理が行われます。IParameterInspector はまさにそれです。各呼び出しの前後に、インスペクターは操作の入力、出力、および戻り値を検査する機会を得ます。

これは、次のことを示す完全なコマンド ライン プログラムです。

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace WCFClientInspector
{
    public class OperationLogger : IParameterInspector
    {
        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
            Console.WriteLine("Completed operation:" + operationName);
        }

        public object BeforeCall(string operationName, object[] inputs)
        {
            Console.WriteLine("Calling operation:" + operationName);
            return null;
        }
    }

    public class OperationLoggerEndpointBehavior : IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            foreach (ClientOperation operation in clientRuntime.ClientOperations)
            {
                operation.ClientParameterInspectors.Add(new OperationLogger());
            }
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }


    [ServiceContract]
    public interface ISimple
    {
        [OperationContract]
        void DoSomthing(string s);
    }

    public class SimpleService : ISimple
    {
        public void DoSomthing(string s)
        {
            Console.WriteLine("Called:" + s);
        }
    }

    public static class AttributesAndContext
    {
        static void Main(string[] args)
        {
            ServiceHost simpleHost = new ServiceHost(typeof(SimpleService), new Uri("http://localhost/Simple"));
            simpleHost.Open();

            ChannelFactory<ISimple> factory = new ChannelFactory<ISimple>(simpleHost.Description.Endpoints[0]);
            factory.Endpoint.EndpointBehaviors.Add(new OperationLoggerEndpointBehavior());
            ISimple proxy = factory.CreateChannel();

            proxy.DoSomthing("hi");

            Console.WriteLine("Press ENTER to close the host.");
            Console.ReadLine();

            ((ICommunicationObject)proxy).Shutdown();

            simpleHost.Shutdown();
        }
    }

    public static class Extensions
    {
        static public void Shutdown(this ICommunicationObject obj)
        {
            try
            {
                obj.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Shutdown exception: {0}", ex.Message);
                obj.Abort();
            }
        }
    }
}

出力が得られるはずです:

  Calling operation:DoSomthing 
  Called:hi 
  Completed operation:DoSomthing
  Press ENTER to close the host.
于 2013-04-16T20:15:30.523 に答える
3

reply.Headers.Actionとはどうですかrequest.Headers.Action。もちろん、残りは問題のリンクと同じようにトリッキーです。したがって、完全なコードは次のようになります。

var action = reply.Headers.Action.Substring(reply.Headers.Action.LastIndexOf("/", StringComparison.OrdinalIgnoreCase) + 1);

また

var action = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf("/", StringComparison.OrdinalIgnoreCase) + 1);
于 2013-04-16T06:33:11.080 に答える