5

내 모델에 원형 개체 그래프가 있지만 그럴 수밖에 없습니다.웹 API에서 빈 500 HTTP 상태 코드 받기

this article에 제공된 조언에 따라 DataContractAttribute을 사용했으며 모든 구성원에 IsReference = true을 설정했습니다. 또한 serialize하려는 모든 속성에 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

모든 클래스가 부분이다 : 당신이 위해 Application_Start시에 XML 포맷을 제거 할 수있는 해결 방법으로

? 클래스의 다른 부분도 속성으로 표시되거나 필요하지 않은 항목입니까? –

+0

이것이 부분 클래스없이 발생하는 것을 확인할 수 있지만 내 경우에는 근본 원인이 가상 탐색 속성 (직렬화로 표시되지 않음)을 사용하는 것으로 나타납니다. WCF 서비스에 사용할 수있는 ProxyDataContractResolver + IObjectBehavior 솔루션과 비슷한 이와 유사한 해결 방법이 필요합니다. –

+0

당신은 이것을 보았습니까 : http://stackoverflow.com/questions/11851207/prevent-property-from-being-serialized-in-web-api 또는 this one http://stackoverflow.com/questions/1411577/ net-json-serialization-like-xmlignore 중 -field-field-ignore를 무시합니다. –

답변

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 포매터를 교체하는 방법을 보여줍니다. - 그 추가 문제가 발생할 수

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

모르겠어요 WebAP 나도 그래,하지만 당신은 ProxyDataContractResolver을 사용하여 WCF에서 같은 문제를 해결했다. 다행히도 WebAPI에 비슷한 고리가 있습니까?

+0

이것은 ApiController에 적용되지 않는다. WCF 서비스와 동일한 방식 (방금 테스트되었습니다.) –

관련 문제