メッセージ インスペクターを追加して、WCF パイプラインを拡張する必要があります。クライアントのメッセージ インスペクターはヘッダーの追加を担当し、サーバーのメッセージ インスペクターはヘッダーが存在するかどうかの検証を担当します。
グッド プラクティス: カスタム ヘッダーを作成する場合は、検索を容易にするカスタム名前空間を指定します。
public static class WCFSOAPNamespaces
{
private const string root = "http://www.schemas.productname.com/";
public const string Headers = root + "headers/";
}
サーバ
はIDispatchMessageInspector
、サーバーへのすべての着信メッセージを処理します。これは、サーバー上にヘッダーが存在するかどうかを確認する場所です。
public class DispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
const string headerName = "nameOfTheHeader";
var someHeaderData = request.Headers.GetHeader<string>(headerName, WCFSOAPNamespaces.Headers);
//someHeaderData is the content that you want to check for every request. Attention: it throws System.ServiceModel.MessageHeaderException if the header doesn't exist
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) { }
}
クライアント
は、クライアント上のIClientMessageInspector
メッセージを処理します。メッセージにカスタム ヘッダーを追加する必要がある場合は、ここを参照してください。カスタム ヘッダーを追加する必要がない場合は、この最初のコードにジャンプできます。
public class ClientMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState) { }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
const string headerName = "nameOfTheHeader";
string headerContent = ""; //fill this variable with the content
var header = new MessageHeader<string>(headerContent ?? string.Empty);
var untyped = header.GetUntypedHeader(headerName, WCFSOAPNamespaces.Headers);
request.Headers.Add(untyped);
return null;
}
}
両方 (クライアントとサーバー)
クライアントにメッセージ インスペクターが必要ない場合でも、サーバー側アプリケーションにメッセージ インスペクションを追加するには、この構成が必要です。具体的にはEndpointBehavior
、MessageInspector を処理するために が必要です。次に、このカスタム エンドポイント動作を使用するようにサービス エンドポイントを設定する必要があります。
この例では、2 つのインスペクタを同じビヘイビアに配置しましたが、必要に応じて別のビヘイビアを作成できます。
public class EndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public EndpointBehavior() { }
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new ClientMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new DispatchMessageInspector());
}
public void Validate(ServiceEndpoint endpoint) { }
public override Type BehaviorType
{
get { return this.GetType(); }
}
protected override object CreateBehavior()
{
return new EndpointBehavior();
}
}
次に、この動作を使用するようにエンドポイントを設定します。
プログラムによる
...
ServiceEndpoint endpoint;
...
endpoint.Behaviors.Add(new EndpointBehavior());
設定
...
<services>
<service name="...">
<endpoint address="..." binding="..." contract="..." behaviorConfiguration="endpointBehaviorName" />
</service>
...
<behaviors>
...
<endpointBehaviors>
<behavior name="endpointBehaviorName">
<customEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
...
<extensions>
<behaviorExtensions>
<add name="customEndpointBehavior" type="FullNamespace.EndpointBehavior , AssemblyName" />
</behaviorExtensions>
</extensions>
これ以降、すべてのリクエストはこのポイントを通過します。それが役に立てば幸い。