問題: WCF サービスの呼び出し中に以下のエラーが発生します。
インデックスが配列の範囲外だった。System.ServiceModel.Dispatcher.DispatchOperationRuntime.InspectInputsCore(MessageRpc& rpc) で System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) で System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) で System.ServiceModel.Dispatcher.ImmutableDispatchRuntime .ProcessMessage4(MessageRpc& rpc) で System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) System.IndexOutOfRangeException
この問題を解決するには助けが必要です。
詳細: 以下のように作成された複数の WCF サービスを Web ホスト (同じ仮想ディレクトリ内、ASP.NET 互換性が有効、baic http バインディング内) にしました。
6 サービスごとに個別のサービス コントラクトと、操作ごとにそれぞれのデータ コントラクトを持つサービス。Message Inspector を追加するカスタム サービス ホスト ファクトリを使用
以下の方法でホストされる 2 つのサービス 以下のコントラクトを実装する同じサービス エンドポイントを指す 2 つの別個の wsdl (スキーマが異なる設計時ファイル)。Message Inspector も追加する別のカスタム サービス ホスト ファクトリを使用します。
[ServiceContract]
public interface IGenericService
{
[OperationContract(Action = "*", ReplyAction = "*")]
System.ServiceModel.Channels.Message GenericOperation(System.ServiceModel.Channels.Message msgRequest);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ValidateMustUnderstand = false)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GenericService : IGenericService
{
public Message GenericOperation(Message msgRequest)
{
これらのサービスはすべて SOA プラットフォーム (Progress Actional) にプロキシを持っています。Actional は、実際のサービスを呼び出すための直接的なエンドポイントを維持し、実際のサービスを適切に呼び出すことができます。
UnitTest の実行に使用されるサーバーでは、8 つのサービスすべてが正常に動作しています。QA サーバーにデプロイすると、個別のサービス コントラクトを持つ 6 つのサービスはすべて正常に動作しますが、2 つの新しいサービス (設計時の wsdls ファイル) では上記のエラーが発生します。
MessageInspector (失敗したサービス) 内のコードは次のようになります。他の 6 つのサービス セットのその他のインスペクターも同様です。
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return Stopwatch.StartNew();
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Stopwatch watch = (Stopwatch)correlationState;
watch.Stop();
TimeSpan performanceTime = watch.Elapsed;
watch = null;
// Invoke Performance Logging Code
}
}
ServiceTrace は次のようになります。
ServiceHost 'XyzServices.SpecificService' を構築します (個別のサービス契約を持つ 6 つのサービスの 1 つ)
ServiceHost 'XyzServices.SpecificService'を開き
ます 特定のサービスに対して開かれたすべてのエンドポイント リスナ
'specificservice uri' でリッスンし
ます 処理メッセージ 1
処理アクション 'SpecificService.SpecificOperation.SoapAction'
'XyzServices.SpecificService.SpecificOperation' を実行
ServiceHost 'XyzServices.GenericService' を構築
処理メッセージ 2
From: 'XyzServices.SpecificService endpoint' でリッスンする
アクティビティ境界 Start
To: プロセス アクション 'GenericService.GenericOperation.SoapAction'
To: 'XyzServices.SpecificService endpoint' でリッスンする
アクティビティ境界 Stop
ServiceHost 'XyzServices.GenericService' を開きます
汎用サービス用に開かれたすべてのエンドポイント リスナー
処理アクション「GenericService.GenericOperation.SoapAction」
From: メッセージ 2 の処理中
アクティビティ境界の開始
チャネル経由でメッセージを受信- メッセージ ヘッダーは正常に見えます。メッセージ本文は表示されません
ServiceChannel 情報- ここではすべて問題ないようです (ユニット テスト サーバーと QA サーバー)
例外の処理- 質問の詳細に貼り付けられた例外を
表示します (
QA
サーバー
のみ) (サービスが単体テスト サーバーで実行されている場合、このアクティビティは問題ないように見えます)
初めてサービストレースビューアーを使用しましたが、特定のサービスに関連するアクティビティから「処理メッセージ 2」アクティビティが開始されることに気付きました。それは、サービスがホストされる方法に問題があることを示していますか? (これらのサービスを分離する必要がある場合) 詳細が必要な場合はお知らせください。
this.InitializeCallContext(ref rpc);
object target = rpc.Instance;
this.DeserializeInputs(ref rpc);
**this.InspectInputs(ref rpc);**
ValidateMustUnderstand(ref rpc);
IAsyncResult result = null;
IDisposable impersonationContext = null;
IPrincipal originalPrincipal = null;
bool isThreadPrincipalSet = false;
try
{
if (this.parent.SecurityImpersonation != null)
{
this.parent.SecurityImpersonation.StartImpersonation(ref rpc, out impersonationContext, out originalPrincipal, out isThreadPrincipalSet);
}
void InspectInputsCore(ref MessageRpc rpc)
{
int offset = this.Parent.ParameterInspectorCorrelationOffset;
for (int i = 0; i < this.ParameterInspectors.Length; i++)
{
IParameterInspector inspector = this.ParameterInspectors[i];
rpc.Correlation[offset + i] = inspector.BeforeCall(this.Name, rpc.InputParameters);
}
}