2011-02-08 10 views
1

私は専門家の助けが必要です。 MyExceptionというカスタムクラスがあります。このクラスの目的は、カスタム情報で例外を記録することです。ここに示したように、このクラスの定義は次のとおりです。WCFとSilverlightのシリアル化

[DataContract] 
public class MyException 
{ 
    [DataMember] 
    public string StackTrace { get; set; } 

    [DataMember] 
    public string Message { get; set; } 

    [DataMember] 
    public string Component { get; set; } 

    [DataMember] 
    public string TypeName { get; set; } 

    [DataMember] 
    public string Miscellaneous { get; set; } 

    public MyException() 
    {} 

    public MyException(string message) 
    { 
    this.Message = message; 
    } 

    public MyException(string message, string stackTrace) 
    { 
    this.Message = message; 
    this.StackTrace = stackTrace; 
    } 
} 

私はJSON形式でMyExceptionを受け入れ、それがデータベースへの内容だ書き込むことが意図されるWCFサービスを提供しています。私が追跡しようとする情報の量のために、私はPOST操作を使用する必要があるので、私は実装off this blog postのベースにすることにしました。私のサービスの説明はここで見つけることができます:

[OperationContract] 
[WebInvoke(UriTemplate="/LogError", Method="POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
public string LogError(Stream stream) 
{ 
    try 
    { 
    DataContractJsonSerializer serializer = 
     new DataContractJsonSerializer(typeof(MyException)); 
    MyException exception = (MyException)(serializer.ReadObject(stream)); 
    // Write the exception details to the database 
    } 
    catch (Exception ex) 
    { 
    // Write the exception details to the database 
    } 
} 

[OperationContract] 
public void Test(MyException exception) 
{ } 

MyExceptionは私のSilverlightアプリケーションにプロキシの生成時にさらされることになるように、私は「テスト」の操作を追加しました。次のコードを使用してのlogErrorに投稿するために私のSilverlightアプリケーションの試み:

MyServiceProxy.MyException exception = new MyServiceProxy.MyException(); 
exception.Message = e.Error.Message; 
exception.StackTrace = e.Error.StackTrace; 
exception.Component = GetComponentName(); 
exception.TypeName = e.Error.FullName; 

string json = string.Empty; 
using (MemoryStream stream = new MemoryStream()) 
{ 
    DataContractJsonSerializer serializer = new 
    DataContractJsonSerializer(typeof(MyServiceProxy.MyException)); 
    serializer.WriteObject(stream, exception); 

    stream.Position = 0; 
    using (StreamReader reader = new StreamReader(stream)) 
    { 
    json = reader.ReadToEnd(); 
    } 

    Uri uri = new Uri("/myService.svc/LogError", UriKind.Absolute); 
    WebClient myService = new WebClient(); 
    myService.UploadStringCompleted += 
    new UploadStringCompletedEventHandler(myService_UploadStringCompleted); 
    myService.Headers["Content-type"] = "application/x-www-form-urlencoded"; 
    myService.Encoding = Encoding.UTF8; 
    myService.UploadStringAsync(uri, "POST", json); 
} 

私はこのコードを実行すると、私は言う私のSilverlightアプリでエラーが出る:データコントラクト名を持つ 「タイプ 『MyServiceProxy.MyExceptionを』 ' MyException:http://schemas.datacontract.org/2004/07/MyNamespace 'は期待されていません。既知の型のリストに静的に知られていない型を追加します。たとえば、KnownTypeAttribute属性を使用するか、リストに追加しますDataContractSerializerに渡される既知の型の "

私は間違っていますか?

+0

なぜあなたは車輪を再発明していて、あなたはSystem.Exceptionからあなたのカスタム例外を派生しないのですか? –

+0

@Davide Piras:.NET例外は** WCF通信には適していません** - WCF通信は相互運用可能で、SOAPエラーのみを使用する必要があります(詳細なエラー情報を保持するためにカスタムクラスがよく使用されます) –

+0

こんにちは、私はいつも.NETの例外が設計によって直列化可能だと思っていましたので、それらを使用するのは大丈夫です:) –

答えて

0

ここで問題はあなたのタイプが異なっていること、プロキシクラスを使用してシリアライズしていること、そしてサーバー側に戻すときに別のタイプとしてデシリアライズしようとしていると思います。

KnownType属性を追加できるはずです。自動生成されたプロキシクラスでこれが必要になると思います。

+0

私は彼らがどのように異なるタイプであるか分かりません。サービスプロキシがサービスの定義に基づいてサービスプロキシを生成している場合、それは同じではないでしょうか? – user70192

+0

これらは異なる名前空間にあり、具体的な実装はもう一方はオブジェクトに似ていますが同じではない自動生成プロキシです。 WCF/Silverlightに同じオブジェクトを共有させることができますが、2つのプロジェクトを共有するためにはさらに多くのプロジェクトを作成する必要があります。 –

+0

これを行う別の方法はありますか?またはこれが唯一の方法です。これをJSONに簡単にシリアライズできないのは奇妙なことです。 – user70192

0

DataContract属性で明示的に名前空間を設定したとします。 [DataContract(Namespace = "http://tempuri.org/2010/etc")]のようなものなので、シリアライザはクラスを同じものとして扱います。

私はそれを試してみましょう。名前空間を追加して参照を再生成する。

0

要求のコンテンツタイプが "application/x-www-form-urlencoded"であることをリクエストで指定します。しかし、コンテンツは実際にはJSON(DataContractJsonSerializerを使用して生成)です。 content-typeを正しいもの( "application/json")に更新してみてください。そうすれば、必要な場所にさらにアクセスできるようになります。

関連する問題