5

Próbuję wypisać listę obiektów do formatu json przy użyciu klasy DataContractJsonSerializer, ale nadal napotykam następujący błąd.Problem DataContractResolver/KnownType, gdy niestandardowa klasa zawiera inną niestandardową klasę

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. 

Wiem, że zostało to wcześniej odpowiedział, ale wydaje się, że dzieje się tylko wtedy, gdy w moim obiekcie ma właściwość, która jest innym niestandardowym obiektem.

[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; } 
} 

Jak widać model Joke zawiera obiekt Joke kategorię, jeśli usunąć Joke kategorii i po prostu mieć int (JokeCategoryId) błąd nie zaniknie, chociaż rozwiązania, nie idealnym jeden jak chciałbym aby udostępnić kategorię bez konieczności ponownego zapytania.

Poniżej znajduje się kod używam do generowania 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 
      }; 
     } 
    } 

Co myli mnie najbardziej to, że wzmianki o błędach Castle.Proxies.JokeCategoryProxy (skąd się to wzięło ?!)

Wszelkie sugestie?

Odpowiedz

5

nHibernate zakłada, że ​​wszystkie twoje właściwości, o ile nie podano inaczej, są załadowane leniwo.
Co oznacza, że ​​w twoim przypadku JokeCategory nie zostanie wyciągnięty z bazy danych za każdym razem, gdy ciągniesz swój obiekt Joke; zamiast tego "proxy" jest generowane dynamicznie.
Przy pierwszym dostępie do tej właściwości nHibernate wie, aby wyciągnąć ją z bazy danych. (Tak to działa lazy-loading nHib'S)

Więc w zasadzie to, co się tutaj dzieje jest to, że można oczekiwać, aby być twój JokeCategory typu JokeCategory, ale ponieważ nie jest naprawdę initialized- to od rodzaju Proxy....

(to tylko krótkie wyjaśnienie; google trochę więcej na nHib i jak to działa, aby dowiedzieć się więcej można również sprawdzić summer of nhibernate dla wielkiej wstępie do niniejszego ORM).

A na pytanie: masz kilka możliwości:

  1. skonfiguruj właściwość kategorię jako non-leniwy, która zmusi NHibernate zainicjować go z właściwego typu obiektu

  2. (znacznie bardziej korzystne, moim zdaniem) czy n ot serializować twoje Modelowe jednostki; zamiast tego - zbuduj jakiś DTO, który pomieści dowolne informacje, których potrzebuje twoja warstwa prezentacji.
    W ten sposób zmiany w modelu domenowym nie muszą mieć wpływu na prezentację i na odwrót.
    możesz również przechowywać wszystkie niezbędne informacje w swoim urządzeniu DTO, nawet jeśli jest on powiązany z więcej niż jedną jednostką modelu.

Na przykład:

public class JokeDTO 
    { 
     public int JokeId; 
     /*more Joke properties*/ 
     public int JokeCategoryId; 
     public string JokeCategoryName; 
     /*etc, etc..*/ 
    } 
+0

Bardzo przydatne rzeczy sJhonny. Na razie nie będę wchodził do DTO, ale będę ich pamiętał o przyszłym rozwoju. Używanie .Not.LazyLoad() w moim płynnym nhibernate pliku mapowania działa idealnie, aby rozwiązać natychmiastowy problem. Dziękuję Ci bardzo. – JConstantine