WCF和Silverlight之间的序列化

时间:2011-02-08 14:34:57

标签: c# silverlight wcf serialization

我需要专家的帮助。我有一个名为MyException的自定义类。此类的目的是使用自定义信息记录异常。这个类的定义如下所示:

[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;
  }
}

我有一个WCF服务,旨在接受JSON格式的MyException并将其内容写入数据库。由于我打算跟踪的信息量,我需要使用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)
{ }

我添加了“Test”操作,以便在代理生成期间将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应用程序中收到错误消息: “不要求使用数据协定名称'MyException:http://schemas.datacontract.org/2004/07/MyNamespace'输入'MyServiceProxy.MyException'。将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。“

我做错了什么?

3 个答案:

答案 0 :(得分:0)

我认为这里的问题是你的类型不同,你正在使用代理类并对其进行序列化,然后在服务器端将它重新反序列化为另一种类型。

您应该能够添加KnownType属性,我相信在自动生成的代理类中需要这样做。

答案 1 :(得分:0)

如果您在DataContract属性上显式设置名称空间,则可能。 像[DataContract(Namespace = "http://tempuri.org/2010/etc")]之类的东西,所以序列化程序会将类视为相同。

我会尝试一下。添加命名空间并重新生成引用。

答案 2 :(得分:0)

您在请求中指定请求的内容类型为“application / x-www-form-urlencoded”。但内容实际上是JSON(使用DataContractJsonSerializer生成)。尝试将内容类型更新为正确的内容类型(“application / json”),这样可以让您进一步了解所需内容。