2011-02-08 60 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應用程序。我的Silverlight應用程序嘗試使用下面的代碼發佈到LOGERROR:

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派生你的自定義異常! – 2011-02-08 14:56:30

+0

@Davide Piras:.NET異常對於WCF通信來說不是很好 - WCF通訊應該是可互操作的,並且應該只使用SOAP錯誤(通常伴隨一個自定義類來保存更詳細的錯誤信息) – 2011-02-08 15:13:56

回答

0

我相信這裏的問題是,你的類型是不同的,你使用的代理類和序列化它,然後嘗試反序列化它作爲一個不同的類型,當你得到它在服務器端。

你應該能夠添加KnownType屬性,我相信這將是需要在自動生成的代理類。

0

也許如果您明確地設置DataContract屬性的名稱空間。 像[DataContract(Namespace = "http://tempuri.org/2010/etc")]之類的東西,所以序列化器會將這些類視爲相同的。

我會試試看。添加名稱空間並重新生成參考。

0

您在請求中指定請求的內容類型是「application/x-www-form-urlencoded」。但內容實際上是JSON(使用DataContractJsonSerializer生成)。嘗試將內容類型更新爲正確的內容類型(「application/json」),這應該讓你進一步到達需要的地方。