いくつかのコンテキスト: カスタム XSD があり、WSCF.blue を使用して WSDL および C# コードを生成します。クライアント側はChannelFactory<T>
、XSD の内容と一致するように WSCF.blue によって追加されたすべての属性を含むインターフェースを使用および共有します。
IErrorHandler.ProvideFault
generic を提供する場所を実装しようとしていますFaultException<T>
が、クライアント側では非ジェネリックを取得していますFaultContract
。これは私のProvideFault
方法がどのように見えるかです:
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (!(error is FaultException))
{
FaultException faultException = FaultExceptionFactory.CreateFaultException(error);
MessageFault messageFault = faultException.CreateMessageFault();
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
各サービスメソッドで、try/catch を実行すると期待どおりに動作するので、 、ファクトリ、バインディングなどはすべて正しいthrow FaultExceptionFactory.CreateFaultException(ex)
と思います。[FaultContract]
念のため、工場の仕組みは次のとおりです。
BusinessRuleFaultExceptionType businessRuleFaultException = new BusinessRuleFaultExceptionType();
BusinessRuleFaultException.Code = exception.Code.ToString();
BusinessRuleFaultException.Reason = exception.Message;
return new FaultException<BusinessRuleFaultExceptionType>(
businessRuleFaultException,
exception.Message,
new FaultCode(exception.Code.ToString())
);
IErrorHandler
問題は、メッセージが で、おそらく で作成される方法にあると思いますCreateMessageFault()
。faultException.Action
アクションはの代わりにすべきだと読みnull
ましたが、実際faultException.Action
にはnull
です。たぶん、これが問題の原因です。ファクトリでアクションを設定できますが、アクションはどうあるべきで、なぜそれが手動スローで表示されないのでしょうか?
私が見逃している可能性のある他のアイデアはありますか?
編集: WSDL を確認したところ、呼び出していた特定の操作とそのアクションが見つかりました。
<wsdl:operation name="MyMethod">
<wsdl:fault wsaw:Action="http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault" name="BusinessRuleFaultExceptionTypeFault" message="tns:..."/>
action:Message.CreateMessage(..., "http://myNamespace/MyMethodBusinessRuleFaultExceptionTypeFault")
をハードコーディングして、工場で に設定しようとし.Action
ましたが、それでもうまくいきませんでした。
編集 2: throw/catch は、クライアントで一般的な例外をキャッチできる次の XML を生成します。
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code xmlns="http://myNamespace/Entitites">-100</Code>
<Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
はIHttpErrorHandler
、非ジェネリックに行く以下を生成しますFaultException
:
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://schemas.datacontract.org/2004/07/My.Dot.Net.Namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<codeField>-100</codeField>
<reasonField>xxx</reasonField>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
編集 3:とを
に追加する[DataContract]
と、ほぼ正しい XML が得られます。[DataMember]
BusinessRuleFaultExceptionType
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns="http://myNamespace/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>-100</Code>
<Reason>xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
Code と Reason の名前空間がありません。少なくともこれで絞れると思います。通常のシリアル化では and を使用し、 では[XmlType]
and[XmlElement]
をIErrorHandler
使用[DataContract]
してい[DataMember]
ます。残念ながら[DataMember]
、名前空間を設定することはできません。そのため、問題は .xml で XMLSerializer を使用する方法だと思いますIErrorHandler
。これは私の問題を説明していますが、上記の理由で修正は機能しません: http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html
編集 4:
問題を部分的に見つけました。を使用してXmlSerializer
いIErrorHandler
ますが、運用範囲外のため、デフォルトの に戻しますDataContractSerializer
。解決策は、サービスをどこでも使用するように変更するか、障害を作成するときにDataContractSerializer
手動で選択することです。XmlSerializer
これらの 2 つの記事は、私が必要としていたものを提供してくれました。
http://twenty6-jc.blogspot.com/2011/05/ierrorhandlerprovidefault-serialization.html http://zamd.net/2008/08/15/serializing-faults-using-xmlserializer/
それは私を非常に近づけます。例外タイプの名前空間がないことを除いて、これは作業中の XML と同じです。
<s:Fault>
<faultcode xmlns="">s:-100</faultcode>
<faultstring xml:lang="en-US" xmlns="">xxx</faultstring>
<detail xmlns="">
<BusinessRuleFaultExceptionType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code xmlns="http://myNamespace/Entitites">-100</Code>
<Reason xmlns="http://myNamespace/Entitites">xxx</Reason>
</BusinessRuleFaultExceptionType>
</detail>
</s:Fault>
xmlns="http://myNamespace/Services"
リクエストのコンテキストがないため、追加されないと思います。その名前空間はインターフェイスで定義されていますが、データ コントラクトでは定義されていません。IOperationInvoker
を使用する代わりに、リクエストのコンテキスト内にとどまることを本当に強制されるのIHttpHandler
でしょうか(うまくいけばうまくいきます)。