もう少し深く掘り下げて、新しい詳細を発見しました。
一般に「UriTemplate」が「AfterReceiveRequest」の 2 回目の呼び出しを引き起こすのではなく、内部のオプションのパラメーターが原因です。
メソッドを呼び出すと
http:///myserver/result/val1
AfterReceiveRequest は 2 回呼び出されます。
次のようなすべての可能なパラメータを渡すと
http:///myserver/result/val1/val2/val3
無駄な呼び出しはありません。その動作は意図したとおりですか?
UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}"
--- 最初の投稿に続き、参考までに ---
WCF REST サービス システムを実装しているときに、http ヘッダーの問題に行き詰まりました。
私の中には、属性で定義されServiceContractたメソッドがあるので、経由で呼び出すことができますUriTemplateWebGet
http://server/resource/val1/val2 ...
それ以外の
http://server/resource?para1=val1¶2=val2 ...
(互換性の理由からこれが必要です。)
また、http-headersコレクションには重要な値があり、それを読む必要があります。IDispatchMessageInspectorしたがって、このインスペクターを実装してEndpointDispatchers MessageInspectorsコレクションに追加します。これにより、AfterReceiveRequestWCF によって呼び出され、アクセスWebOperationContext.Current.IncomingRequest.Headersして目的の値を読み取ることができます。
問題:
WCFUriTemplateは、宛先メソッドへの 2 番目の要求を生成することによって -mapping を解決しますが、元の呼び出しから生成された 2 番目の呼び出しにヘッダー エントリを渡しません。そのためAfterReceiveRequest(そしてもちろんBeforeSendReplyも) は 2 回呼び出されますが、実際のクライアント呼び出しからのヘッダー値は最初の呼び出しにのみ含まれます。
AfterReceiveRequestまた、最初の呼び出しから 2 番目の呼び出しにヘッダー値を渡すための「特別な方法」を実装するために、最初の呼び出しと2 番目の呼び出しを関連付ける方法が見つかりませんでした。
UriTemplate-redirected 2 番目の呼び出しにヘッダーをルーティングするように WCF に指示する方法はありますか?
明確にするために、いくつかのコードフラグメントを次に示します。
[ServiceContract]
public interface IMyService
{
[WebGet(UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}")]
bool MyMethod(string para1, string para2, string para3);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
[MyServiceInspectorBeavior]
public class MyService : IMyService
{
public bool MyMethod(string para1, string para2, string para3)
{
return DoTheWork();
}
//...
}
public class MyServiceInspectorBeavior : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (EndpointDispatcher epDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(cDispatcher => cDispatcher.Endpoints))
{
epDispatcher.DispatchRuntime.MessageInspectors.Add(new MyInspector());
}
}
//...
}
public class MyInspector : IDispatchMessageInspector
{
//this is invoked twice for each client request,
//but only at the first call the header is present...
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
WebHeaderCollection webOpContext =
WebOperationContext.Current.IncomingRequest.Headers;
string xForwardedIp = webOpContext["X-FORWARDED-IP"];
WriteLog(xForwardedIp);
return OperationContext.Current.IncomingMessageProperties["ActivityId"];
}
//...
}