5

モデルに円形のオブジェクトグラフがありますが、それは避けられません。

この記事で与えられたアドバイスに従って、私はすべてのメンバーに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)循環参照を削除します。理由:これらの種類の参照は、EntityFrameworkで生成されたモデルでは非常に一般的です。モデルに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;
        }
    }
}
4

2 に答える 2

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

このドキュメントでは、web-apiコントローラーで使用されるフォーマッターを構成する方法、循環参照を処理する方法、およびデフォルトのxmlフォーマッターを再構成/置換する方法についても説明します。

回避策として、Application_Start中にxmlフォーマッターを削除できます。

var xmlFormatter = config.Formatters.XmlFormatter;
if (xmlFormatter != null)
{
    config.Formatters.Remove(xmlFormatter);
}
于 2013-01-16T20:59:43.333 に答える
0

WebAPIについてはよくわかりませんが、ProxyDataContractResolverを使用してWCFで同じ問題を解決します。うまくいけば、WebAPIにも同様のフックがありますか?

于 2013-01-10T13:03:25.207 に答える