2012-09-26 32 views
7

Próbuję wdrożyć to, co uważałem za prosty scenariusz za pomocą usługi OData dostarczanej przez usługi danych WCF (przy użyciu formatu OData V3/json; odata = verbose payload, teraz mogę używać formatu JSON Light w przyszłość). Podstawowy scenariusz wygląda tak:Jak zaktualizować encję OData i zmodyfikować jej właściwości nawigacyjne w jednym żądaniu?

Mam dwa podmioty:

class Person 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual PersonCategory Category { get; set; } 
} 

class PersonCategory 
{ 
    public int ID { get; set; } 
    public string Description { get; set; } 
    public virtual ICollection<Person> People { get; set; } 
} 

Teraz chcę utworzyć prostą stronę edycji dla danej osoby. Ta strona edycji może mieć dane wejściowe dla Nazwy oraz dane wejściowe lub listę rozwijaną dla kategorii Osoby.

Więc scenariusz idzie:

  1. Kod pobiera osoba korzystająca $ poszerzyć dla kategorii: GET /api.svc/People(1)?$expand=Category
  2. użytkownik edytuje zarówno osoby Nazwa własności i ich kategoria.
  3. Kod strony składa się z pojedynczego żądania aktualizacji właściwości tej osoby i kategorii.

Klucz jest tutaj w "pojedynczej prośbie". To jest część, z którą mam problem ze znalezieniem dokumentacji. Widziałem przykłady, w których dzielą liczbę 3 powyżej na dwie prośby. Coś takiego (nie pamiętam dokładnie formatu - Jestem też pewien, czy nie trzeba by usunąć linki Kategoria przed wykonaniem put):

PATCH /api.svc/People(1) with content: {"Name": "new name" } 
PUT /api.svc/People(1)/$links/Category with content: { "url": "/api.svc/Categories(2)" } 

Ale, ja też je słyszał powiedział, ale nie wykazał, że można zaimplementować niniejszĘ ... aktualizację jako pojedyncze żĘ ... danie ze zmianĘ ... w właś ciwoś ci nawigacji kategorii okreś lonej zgodnie z innymi zmianami do jednostki osoby. Czy ktoś mógłby mi podać przykład tego, jak można to zrobić? Czy możesz mi pokazać, jak można to zrobić za pomocą właściwości nawigacji "wiele do wielu", w przeciwieństwie do jednego z wielu, które opisałem powyżej.

I wreszcie, używam obecnie pełnego formatu JSON, V3. Czy twoje odpowiedzi na powyższe pytania będą inne, jeśli zamiast tego użyję nowego formatu światła JSON? Jeśli tak to jak?

+0

Można wysłać wniosek wsadowy - byłby to pojedynczy wniosek zawierający obie operacje. – Pawel

+0

Czy nie ma innego sposobu, aby zrobić to inaczej niż żądanie wsadowe? To by dodało dodatkowej złożoności do kodu rundy w obie strony po stronie klienta, którego wolałbym uniknąć. Idealnie chciałbym sformatować moje zgłoszenie PATCH/api/Activity (1), aby było to coś w rodzaju: {"category": {"__deferred": {"uri": "/api.svc/Categories(2)"} }} Wydaje się to jednak nie działać. Otrzymuję odpowiedź 204, ale właściwość pozostaje niezmieniona po stronie serwera. –

+0

Tak zwane aktualizacje głębokie (które jest tym czego szukasz) nie są obsługiwane przez usługi danych WCF. W rzeczywistości nawet sama OData tak naprawdę jej nie definiuje. Może się to dość skomplikować w niektórych przypadkach. Obawiam się, że partia to jedyne rozwiązanie. Głębokie wstawki są obsługiwane (ale znowu tylko wstawki, nie modyfikując niczego istniejącego). –

Odpowiedz

4

komentarz Pratik była odpowiedź (Pratik jeśli chcesz odśwież to jako odpowiedź, będę oznaczyć go jako takiego - dzięki!):

Pytanie: Czy chcesz zaktualizować kategorię instancja lub czy chcesz zaktualizować niektóre właściwości instancji kategorii. Nie ma sposobu, aby zrobić to później niż partia. W przypadku pierwszego możesz zrobić coś takiego: {"Nazwa": "nowa nazwa", "Kategoria": {"__metadata": {"uri": "/api.svc/Categories(2)"}}}. Mam nadzieję że to pomoże. - Pratik

+0

Hmm to nie działa dla mnie z aktualizacjami i tak – rethenhouser2

+0

Hmm działa, kiedy używam pełnego url \ uri dla metadanych linku, ok, wtedy. – rethenhouser2

4

Znalazłem dwa sposoby reprezentują właściwości nawigacyjnych inline:

application/json;odata=verbose - { "Name": "new name", "Category": { "__metadata": { "uri": "Categories(2)" }}}

application/json - { "Name": "new name", "[email protected]": "Categories(2)" }

+0

Twój pierwszy przykład to specyfikacja OData 3.0. Twoja druga to OData 4.0 – JDB

0

Nie trzeba partię, już. Możesz to zrobić w jednym połączeniu. Po prostu musisz również wysłać zmienione właściwości i pozwolić repozytorowi obsłużyć zmienione właściwości.

public class Person 
{ 
    public string FirstName {get;set;} 
    public string LastName {get;set;} 
    public int Age {get;set;} 
} 

Powiedzmy można zauważyć pierwsze imię ma literówkę, Jhon i to ma być John. Możesz edytować imię i wysłać je. Więc masz następujący model obiektu. Formularz ten można uzyskać w 1 z dwóch sposobów:

  • mają dwa parametry i ustawić BodyStyle = WebMessageBodyStyle.Wrapped
  • Wystarczy utworzyć rodzajowego modelu obiektu z dwóch właściwości: Właściwość jeden jest typu T i mienia 2 jest lista.

Więc chcesz wysłać tę json:

[{ FirstName = 'John' }, ['FirstName']] 

Teraz po stronie serwera, można zrobić to, co trzeba zrobić.

Jeśli nie chcesz wysyłać zmienionych właściwości, możesz odgadnąć zmienione właściwości, wybierając dowolną właściwość, której wartość nie jest domyślną własnością.

{FirstName = „John”}

Następnie można skorzystać z kilku metod, aby zobaczyć, jakie właściwości zostały zmienione:

  • kod klienta na jednostkę, aby upewnić się, że każda nieruchomość nie jest wartością domyślną i ustaw to. Wymaga kawałka kodu na jednostkę.
  • Odbicie, aby upewnić się, że każda właściwość nie jest wartością domyślną. Wymaga 1 klasy dla wszystkich podmiotów. Zrobiłem to w 2014 r. Tutaj w Entity Framework: http://www.rhyous.com/2014/12/01/entityupdater-generic-helper-for-entity-framework/