2011-02-08 42 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”),这应该让你进一步到达需要的地方。