5

我的模型中有一個圓形的對象圖,但這是不可避免的。從Web API獲取空的500 http狀態碼

根據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; 
     } 
    } 
} 
+0

所有的類都是部分 - 可能會導致其他問題?類的其他部分是否也用屬性標記或者不是必需的? –

+0

我可以確認這發生沒有部分類,但是,在我的情況下,根本原因似乎是使用虛擬導航屬性(未標記爲序列化)。這需要一個乾淨的解決方法,類似於可用於WCF服務的ProxyDataContractResolver + IObjectBehavior解決方案。 –

+0

你有沒有試過期待這個:http://stackoverflow.com/questions/11851207/prevent-property-from-being-serialized-in-web-api或這一個http://stackoverflow.com/questions/1411577/忽略字段在網絡json序列化類似於xmlignore –

回答

2

解決方案

這個問題在AspNetWebStack每日構建解決。

我沒有跟蹤哪個簽入可以糾正行爲,因爲我在跟蹤多個問題。

您可以通過將http://www.myget.org/F/aspnetwebstacknightly/添加到程序包管理器配置中,然後從該附加存儲庫中明確更新來更新解決方案,以使用最新的夜間程序包。

據我所知,在1/18夜間是我的解決方案中的穩定(OData的查詢返回快得多好。)

解決方法

如果您無法使用最新的aspnetwebstack構建,如果您不需要XML格式的源,則有一種潛在的解決方法。

http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

本文檔介紹瞭如何配置網絡API控制器使用的格式化,它也顯示瞭如何處理循環引用,以及如何重新配置​​/替換默認XML格式。

作爲一種變通方法,您可以在的Application_Start刪除XML格式:

var xmlFormatter = config.Formatters.XmlFormatter; 
if (xmlFormatter != null) 
{ 
    config.Formatters.Remove(xmlFormatter); 
} 
0

我不知道WebAP我很好,但你通過使用ProxyDataContractResolver來解決WCF中的相同問題。希望WebAPI有一個類似的鉤子?

+0

這似乎並不適用於ApiController與WCF服務相同的方式(剛測試過)。 –

相關問題