【发布时间】:2012-12-24 20:53:06
【问题描述】:
我的模型中有一个圆形对象图,但这是不可避免的。
根据this article 中给出的建议,我对所有成员都使用了DataContractAttribute 并设置了IsReference = true。我还在我想要序列化的所有属性上提供了DataMemberAttribute。
为了确保序列化器不会再遇到任何问题,我只选择不来序列化导航属性。
但是,我的 catch 块中仍然遇到异常。异常详情如下:
_innerException: {"Type
'System.Data.Entity.DynamicProxies.Author_615FB9F8BB22B55A7CA168DA5ED29EC6A0B59F62FD79D1346045351BE2F163A4' with data contract name
'Author_615FB9F8BB22B55A7CA168DA5ED29EC6A0B59F62FD79D1346045351BE2F163A4:
http://schemas.datacontract
.org/2004/07/System.Data.Entity.DynamicProxies' 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."}
我可以但不希望:
1) 禁用代理创建。我可以仅仅为了序列化而删除代理创建,我可能会这样做。但我也想了解为什么我仍然会收到异常以及我能做些什么。
2) 删除循环引用。原因:这些类型的引用在 Entity Framework 生成的模型中非常常见。如果我要做一个模型中有 800 到 1000 个类的大型项目,那么通过删除循环引用来实现它是一场噩梦。
我在下面描述了这个小尖峰解决方案的架构元素。
数据库架构
Id AuthorName
-------------------------------
1 Charles Dickens
2 Charles Petzold
3 Charles Darwin
4 Charles Chaplin
5 Leo Tolstoy
6 Fydor Dostoevsky
7 Ayn Rand
8 Napolean Hill
9 Claude M. Bristol
10 Edward Dwight Easty
11 O. Henry
12 William Shakespeare
13 Juwal Lowy
14 Jeffrey Richter
15 Chris Sells
16 Don Box
17 Steven Pinker
18 Jim Rohn
19 George Eliot
20 Sathyaish Chakravarthy
Id Title AuthorId
----------- -------------------------------------------------- -----------
1 Nicholas Nickleby 1
Id BookId Review
----------- ---------------------------------------------------------------
1 1 How do I know? I haven't read it.
型号
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace BookReviewsModel
{
[DataContract(IsReference = true)]
public partial class Author
{
[DataMember]
public virtual int Id { get; set; }
[DataMember]
public virtual string AuthorName { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
namespace BookReviewsModel
{
[DataContract(IsReference = true)]
public partial class Book
{
[DataMember]
public virtual int Id { get; set; }
[DataMember]
public virtual string Title { get; set; }
[DataMember]
public virtual int AuthorId { get; set; }
public virtual Author Author { get; set; }
public virtual ICollection<BookReview> BookReviews { get; set; }
}
}
namespace BookReviewsModel
{
[DataContract(IsReference = true)]
public partial class BookReview
{
[DataMember]
public virtual int Id { get; set; }
[DataMember]
public virtual int BookId { get; set; }
[DataMember]
[AllowHtml]
public virtual string Review { get; set; }
public virtual Book Book { get; set; }
}
}
控制器代码
namespace BookReviews.Controllers
{
public class AuthorController : ApiController
{
[HttpGet]
public IEnumerable<Author> Index()
{
try
{
using (var context = new BookReviewEntities())
{
var authors = context.Authors.ToList();
var str = Serialize(new XmlMediaTypeFormatter(), authors);
System.Diagnostics.Debugger.Break();
System.Diagnostics.Debug.Print(str);
return authors;
}
}
catch (Exception ex)
{
var responseMessage = new HttpResponseMessage
{
Content = new StringContent("Couldn't retreive the list of authors."),
ReasonPhrase = ex.Message.Replace('\n', ' ')
};
throw new HttpResponseException(responseMessage);
}
}
string Serialize<T>(MediaTypeFormatter formatter, T value)
{
Stream stream = new MemoryStream();
var content = new StreamContent(stream);
formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait();
stream.Position = 0;
return content.ReadAsStringAsync().Result;
}
}
}
【问题讨论】:
-
您的所有课程都是部分课程 - 这会导致任何其他问题吗?类的其他部分是否也标有该属性,还是不需要?
-
我可以确认在没有部分类的情况下会发生这种情况,但是,就我而言,根本原因似乎是使用了虚拟导航属性(未标记为序列化)。需要有一个干净的解决方法,类似于可用于 WCF 服务的 ProxyDataContractResolver+IObjectBehavior 解决方案。
-
我试过 [JsonIgnore]、[IgnoreDataMember] 和 [ScriptIgnore] 都没有成功。为了完整起见,如果我删除测试实体上的唯一导航属性并重新获取,我会看到来自服务器的有效 http 响应。不能移除 nav 属性。
-
如果我从全局配置中删除 XML 格式化程序,我能够收到有效的响应,但我认为这不是解决问题的正确方法。我还是想支持xml序列化。我通过将“GlobalConfiguration.Configuration.Formatters.RemoveAt(1)”添加到 Application_Start 来实现这一点(希望这可以作为其他被同样问题阻止的人的解决方法。)
标签: asp.net asp.net-mvc serialization asp.net-mvc-4 asp.net-web-api