Silverlightを解析してWCF/Reset異常の解決方法を呼び出します。
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
は、ここでServided by zerexceptionをスローします。
public class Service1 : IService1
{
public string GetData(int value)
{
int i = 0;
int j = 5 / i;
return string.Format("You entered: {0}", value);
}
}
はここで注意します。Silverlightクライアントにサービス参照を追加します。名前は:ServiceReference 1.
ページにボタンを追加します。ボタンのClickイベントコードは以下の通りです。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehavior" name="WcfService1.Service1">
</service>
</services>
</system.serviceModel>
運転した結果、次のようになりました。実際の異常は「0で割る試み」と見られていますが、ブラウザの制限のため、すべての異常はNotFoundです。
msdnにはこの問題を解決できる二つの方法があります。
最も簡単なのはApp.xaml.csコードの中でRegister Prfixを使って予備クライアントHTTPスタックを使うことです。
private void Button_Click(object sender, RoutedEventArgs e)
{
Service1Client client = new ServiceReference1.Service1Client();
client.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(client_GetDataCompleted);
client.GetDataAsync(35); //Try GetData
}
void client_GetDataCompleted(object sender, ServiceReference1.GetDataCompletedEventArgs e)
{
}
再度実行コード:これはSLがWCFサービスを呼び出してどうやって異常を処理する方式ですか?
まず、Web.com figノードの下のserviceModelを修正して、Resetをサポートします。
public App()
{
bool bRegisterPrefix = WebRequest.RegisterPrefix(http://localhost:9541/,
WebRequestCreator.ClientHttp);
//other Code
}
ここでwebHttpノードのfault Exception Enbiled=trueを設定し、serviceDebugのinclude Exception Detail InFaultsをtrueとします。OKです。サービスのWeb.com figファイルはもう配置済みです。これからGetData方法にWebGet特性を追加します。
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"
faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ServiceBehavior" name="WcfService1.Service1">
<endpoint behaviorConfiguration="EndpointBehavior" binding="webHttpBinding"
bindingConfiguration="" name="Rest" contract="WcfService1.IService1" />
</service>
</services>
</system.serviceModel>
実行:アドレス:http://localhost:9541/Service1.svc/help
次にアドレスを入力します。http://localhost:9541/Service1.svc/GetData?value=3
異常情報が見られます。
注意:クロスドメインとライセンスファイルの追加を忘れないでください。crossdomain.xmlとclientaccesspolicy.xmlはウェブサイトのルートディレクトリに行きます。
同様に、SLクライアントページを修正し、Buttonを追加しました。
public class Service1 : IService1
{
[WebGet()]
public string GetData(int value)
{
int i = 0;
int j = 5 / i;
return string.Format("You entered: {0}", value);
}
}
実行します。btnResetをクリックしてください。Reset呼び出しの結果はまだNotFoundであることが分かります。
ヒントは私達にレスリングの属性とSttusの属性を確認させます。
Respone属性のResponseStremを見てみましょう。
errorMessageはリターンのエラーであることが分かります。私たちはそれに対してExceptionのオブジェクトに逆順序で列化する必要があります。
まずData ContractSerializerを使ってFault Exceptionクラスに逆順してみます。
私たちは反プロローグをFaultExceptionクラスにしてみましたが、XMLデータのElement名はFaultです。だから失敗しました。もしかしてFault類がありますか?しかし、探してみましたが、Fault類は見つかりませんでした。
しかし,ReadObject法ではverifyObject Nameの再負荷が発見された。
コードを:
private void btnRest_Click(object sender, RoutedEventArgs e)
{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(
wc_DownloadStringCompleted);
wc.DownloadStringAsync(new Uri("http://localhost:9541/Service1.svc/GetData?value=3"));
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
throw e.Error;
}
}
再起動:プログレッシブは成功していますが、プログレッシブ後の値はすべて誤っていることが分かります。
最後にXMLの異常データがある以上、xmlデータを解析して、カスタム異常を使ってみてもいいです。
まずSLFault Exceptionクラスを新設し、Exceptionを継承します。コードは以下の通りです。
DataContractSerializer serializer = new DataContractSerializer(
typeof(FaultException));
//object deserializerObject = serializer.ReadObject(errorStream);
object deserializerObject = serializer.ReadObject(XmlReader.Create(errorStream),false);
の完全なコードは以下の通りです。
public class SLFaultException : Exception
{
public ExceptionDetail Detail { get; set; }
public SLFaultException() { }
public SLFaultException(string message) : base(message) { }
public SLFaultException(string message, ExceptionDetail detail)
: base(message)
{
Detail = detail;
}
}
はFault Exceptionにプログレッシブ化されて失敗しましたが、xmlノードのException Detailは逆シーケンスで戻ってきます。もちろん上の処理WebExceptionのプロセスはパッケージ化されてもいいです。読者は自分で試してみてください。結果は下図のようです