Używam internetowego interfejsu API MVC 4 i formularzy sieci web asp.net 4.0 do tworzenia reszt API. Działa świetnie:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Teraz muszę zapobiec serializacji niektórych właściwości. Wiem, że mogę użyć LINQ na liście i uzyskać tylko te właściwości, których potrzebuję, i ogólnie jest to dobre podejście, ale w obecnym scenariuszu something
obiekt jest zbyt złożony i potrzebuję innego zestawu właściwości w różnych metodach, więc jest to łatwiej jest oznaczyć w czasie wykonywania każdą właściwość do zignorowania.
Czy jest na to sposób?
c#
asp.net
asp.net-mvc
asp.net-web-api
user1330271
źródło
źródło
Odpowiedzi:
ASP.NET Web API jest używany
Json.Net
jako domyślny program formatujący, więc jeśli Twoja aplikacja używa tylko formatu JSON jako formatu danych, możesz użyć[JsonIgnore]
do zignorowania właściwości dla serializacji:Ale w ten sposób nie obsługuje formatu XML. Tak więc, w przypadku, gdy twoja aplikacja musi obsługiwać format XML bardziej (lub tylko obsługiwać XML), zamiast używać
Json.Net
, powinieneś użyć,[DataContract]
który obsługuje zarówno JSON, jak i XML:Aby uzyskać więcej informacji, możesz przeczytać oficjalny artykuł .
źródło
Zgodnie ze stroną dokumentacji interfejsu API sieci Web, Serializacja JSON i XML w ASP.NET Web API, aby jawnie zapobiec serializacji właściwości, której można użyć
[JsonIgnore]
dla serializatora Json lub[IgnoreDataMember]
dla domyślnego serializatora XML.Jednak podczas testów zauważyłem, że
[IgnoreDataMember]
zapobiega to serializacji zarówno dla żądań XML, jak i Json, więc zalecałbym używanie tego zamiast dekorowania właściwości wieloma atrybutami.źródło
[IgnoreDataMember]
nie wydaje się działać z ładowanymi z opóźnieniem obiektami proxy EF 6 (właściwościami wirtualnymi).[DataContract]
i[DataMember]
jednak tak.Zamiast pozwalać, aby wszystko było domyślnie serializowane, możesz zastosować podejście „opt-in”. W tym scenariuszu tylko określone właściwości mogą być serializowane. Robisz to za pomocą
DataContractAttribute
iDataMemberAttribute
, znajdującego się w przestrzeni nazw System.Runtime.Serialization .DataContactAttribute
Jest stosowana do klasy iDataMemberAttribute
jest stosowana do każdego członka chcesz być w odcinkach:Ośmielę się powiedzieć, że jest to lepsze podejście, ponieważ zmusza cię do podejmowania wyraźnych decyzji o tym, co zrobi, a czego nie zrobi poprzez serializację. Pozwala również klasom modelu żyć samodzielnie w projekcie, bez uzależnienia od JSON.net tylko dlatego, że gdzie indziej zdarza się, że serializujesz je za pomocą JSON.net.
źródło
To zadziałało dla mnie: Utwórz niestandardowy program do rozpoznawania umów, który ma publiczną właściwość o nazwie AllowList typu tablicowego. W akcji zmodyfikuj tę właściwość w zależności od tego, co akcja musi zwrócić.
1. utwórz niestandardowy program do rozpoznawania umów:
2. używać niestandardowego narzędzia do rozpoznawania umów w akcji
Takie podejście pozwoliło mi zezwolić / zabronić na określone żądanie zamiast modyfikować definicję klasy. A jeśli nie potrzebujesz serializacji XML, nie zapomnij go wyłączyć w
App_Start\WebApiConfig.cs
swoim interfejsie. W przeciwnym razie interfejs API zwróci zablokowane właściwości, jeśli klient zażąda kodu XML zamiast json.źródło
Pokażę ci 2 sposoby na osiągnięcie tego, czego chcesz:
Pierwszy sposób: Udekoruj swoje pole atrybutem JsonProperty, aby pominąć serializację tego pola, jeśli jest ono puste.
Drugi sposób: jeśli prowadzisz negocjacje z niektórymi złożonymi scenariuszami, możesz użyć konwencji Web Api („ShouldSerialize”), aby pominąć serializację tego pola w zależności od określonej logiki.
WebApi używa JSON.Net i wykorzystuje odbicie do serializacji, więc po wykryciu (na przykład) metody ShouldSerializeFieldX () pole o nazwie FieldX nie zostanie serializowane.
źródło
Spóźniłem się na grę, ale anonimowe przedmioty załatwią sprawę:
źródło
Spróbuj użyć
IgnoreDataMember
właściwościźródło
Prawie to samo, co odpowiedź Greatbear302, ale tworzę ContractResolver na żądanie.
1) Utwórz niestandardowy ContractResolver
2) Użyj niestandardowego narzędzia do rozpoznawania umów w akcji
Edytować:
Nie działało zgodnie z oczekiwaniami (izolowanie programu rozpoznawania nazw na żądanie). Użyję anonimowych obiektów.
źródło
Możesz być w stanie użyć funkcji AutoMapper i użyć
.Ignore()
mapowania, a następnie wysłać zmapowany obiektźródło
Działa dobrze, po prostu dodając: [IgnoreDataMember]
Na górze nieruchomościp, na przykład:
Działa to z ApiController. Kod:
źródło
Z jakiegoś powodu
[IgnoreDataMember]
nie zawsze mi się to udaje, a czasem dostajęStackOverflowException
(lub podobnie). Zamiast tego (lub dodatkowo) zacząłem używać wzorca wyglądającego mniej więcej tak, kiedyPOST
wchodzęObjects
do mojego API:Więc w zasadzie przekazuję an
JObject
i konwertuję go po otrzymaniu, aby uniknąć problemów spowodowanych przez wbudowany serializator, który czasami powoduje nieskończoną pętlę podczas analizowania obiektów.Jeśli ktoś zna powód, dla którego jest to w jakikolwiek sposób zły pomysł, daj mi znać.
Warto zauważyć, że jest to następujący kod właściwości klasy EntityFramework, który powoduje problem (jeśli dwie klasy odwołują się do siebie):
źródło