5

我想输出一个使用DataContractJsonSerializer类的json格式的对象列表,但我一直运行到下面的错误。DataContractResolver/KnownType问题当自定义类包含另一个自定义类

Type 'Castle.Proxies.JokeCategoryProxy' with data contract name 
'JokeCategoryProxy:http://schemas.datacontract.org/2004/07/Castle.Proxies' 
is not expected. Consider using a DataContractResolver or add any types not 
known statically to the list of known types - for example, by using the 
KnownTypeAttribute attribute or by adding them to the list of known 
types passed to DataContractSerializer. 

我知道这已被回答之前,但它似乎只发生在我的对象有一个属性是另一个自定义对象。

[DataContract] 
[KnownType(typeof(ModelBase<int>))] 
public class Joke : ModelBase<int> 
{ 
    [DataMember] 
    public virtual string JokeText { get; set; } 

    [DataMember] 
    public virtual JokeCategory JokeCategory { get; set; } 
} 

[DataContract] 
[KnownType(typeof(ModelBase<int>))] 
public class JokeCategory : ModelBase<int> 
{ 
    [DataMember] 
    public virtual string Name { get; set; } 
} 

正如你所看到的笑话模型包含一个笑话类对象,如果我删除的笑话范畴,只是有一个int(JokeCategoryId)错误消失,虽然一个解决方案,而不是一个理想的,因为我想使分类可用而不必再次查询。

下面是我使用生成JSON

public static ContentResult JsonResponse<TReturnType>(this Controller controller, TReturnType data) 
    { 
     using (var oStream = new System.IO.MemoryStream()) 
     { 
      new DataContractJsonSerializer(typeof(TReturnType)).WriteObject(oStream, data); 

      return new ContentResult 
      { 
       ContentType = "application/json", 
       Content = Encoding.UTF8.GetString(oStream.ToArray()), 
       ContentEncoding = Encoding.UTF8 
      }; 
     } 
    } 

什么混淆我最深的是,错误引用Castle.Proxies.JokeCategoryProxy(谁知道这个来自?)

代码

有什么建议吗?

回答

5

nHibernate假定您的所有属性(除非另有指定)都是延迟加载的。
这意味着,就你而言,只要你拉动你的Joke对象,JokeCategory就不会从数据库中拉出;相反,动态生成“代理”。
您首次访问该属性时,nHibernate知道将其从数据库中提取出来。 (这是nHib的延迟加载是如何工作的)

所以基本上是怎么回事的是,你希望你的JokeCategoryJokeCategory类型的,但因为它是不是真的initialized-它Proxy...类型。

(这只是一个简要的解释;谷歌更多的nHib一些和它是如何工作,以了解更多,您还可以检查出summer of nhibernate为一个伟大的介绍了这个ORM)。

而且,你的问题:你有几个选择这里:

  1. 配置您类别属性作为非偷懒,这将迫使NHibernate的与正确的对象类型来初始化它

  2. (更理想,在我看来)做n ot序列化您的Model实体;取而代之的是构建某种DTO,它可以容纳你的表示层需要的任何信息。
    这样,您的演示文稿不需要受域模型更改影响,反之亦然。
    也可以在DTO中保存所有必要的信息,即使它涉及多个Model实体。

例如:

public class JokeDTO 
    { 
     public int JokeId; 
     /*more Joke properties*/ 
     public int JokeCategoryId; 
     public string JokeCategoryName; 
     /*etc, etc..*/ 
    } 
+0

非常有用的东西sJhonny。目前我不会进入DTOs,但我会记住它们以备未来发展。在流畅的nhibernate映射文件中使用.Not.LazyLoad()可以完美地解决即时问题。非常感谢你。 – JConstantine