我正在尝试使用DataContractJsonSerializer类将对象列表输出为json格式,但是我一直遇到以下错误。
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; }
}
正如你可以看到Joke模型包含一个Joke Category对象,如果我删除了Joke Category并且只是有一个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(这是从哪里来的?!)
有什么建议吗?
答案 0 :(得分:6)
nHibernate假定除非另有说明,否则所有属性都是延迟加载的
这意味着,在您的情况下,每当您拉出JokeCategory
对象时,都不会从数据库中提取Joke
;相反,动态生成'代理'
第一次访问该属性时,nHibernate知道从数据库中取出它。 (这就是nHib的延迟加载方式)
所以基本上这里发生的是你希望你的JokeCategory
属于JokeCategory
类型,但由于它没有真正初始化 - 它的类型为Proxy...
。
(这只是一个简短的解释;谷歌更多关于nHib及其如何工作以了解更多信息。您还可以查看summer of nhibernate以获得对此ORM的精彩介绍)
而且,对于你的问题:你有几个选择:
将Category属性配置为非惰性,这会强制nHibernate使用正确的对象类型初始化它
(在我看来更为可取)不要序列化您的模型实体;相反 - 构建某种DTO,它将保存您的表示层所需的任何信息 这样,您的演示文稿不会受到域模型更改的影响,反之亦然 此外,您可以在DTO中保存所有必要信息,即使它与多个模型实体相关。
例如:
public class JokeDTO
{
public int JokeId;
/*more Joke properties*/
public int JokeCategoryId;
public string JokeCategoryName;
/*etc, etc..*/
}