2012-04-26 12 views
16

Załóżmy mam ten modelasp Web API realizacja łata

public partial class Todo 
{ 
    public int id { get; set; } 
    public string content { get; set; } 
    public bool done { get; set; } 
} 

I mam wysłać ten danych json do mojego kontrolera jako żądanie poprawki. To jest mizernie działanie zaznaczania pola wyboru. Myślę, że to sprawia, że ​​chcę tylko wysłać to na mój serwer, a nie cały model.

{ "id":1, "done" : true } 

Jak powinien wyglądać mój kontroler WebApi, aby poprawnie przetworzyć to proste, jsonowe żądanie poprawki? Czy powinienem używać do tego celu interfejsu webowego, czy też powinienem użyć bardziej zaawansowanego podejścia rpc z mvc?

Wydaje się, że to bardzo podstawowa rzecz, ale nie mogę tego naprawić! Myślę, że może potrzebuję użyć innego parametru w mojej metodzie sterownika, ale nie jestem pewien.

Dziękuję za poświęcony czas.

+0

Można użyć JsonPatch, który jest obsługiwany przez ASP.NET, ASP.NET Core i PCL dla Xamarin. https://github.com/KevinDockx/JsonPatch. Dobry artykuł można znaleźć tutaj http://benfoster.io/blog/aspnet-core-json-patch-partial-api-updates –

+0

Myślę, że to inny problem. Mój model nie jest oparty na jsonie. Sposób, w jaki aktualizacja stanu będzie miała miejsce, powinna należeć do realizatora. Nie chcę tłumaczyć niektórych specyfikacji RFC do zapytania SQL lub mutacji obiektu. –

Odpowiedz

11

Funkcja PATCH można znaleźć w pakiecie Nuget przed premierą: Microsoft.AspNet.WebApi.OData.

Informacja w jaki sposób można go używać do tworzenia działań dla obsługi poprawkę można znaleźć w Częściowe Aktualizacje (żądania Patch) odcinku blogu o OData support in ASP.NET Web API.

+1

Spójrz na ten przykład, aby zrobić patch przez serializator json.net bez zależności od formatów drutu oData - https: //aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/DeltaJsonDeserialization/ –

1

ASP.NET Web API wydaje się, że brakuje UpdateModel, TryUpdateModel itd

w ASP.NET MVC, można ich używać, aby osiągnąć pożądany efekt. Stworzyłem work item w ASP.NET Web Stack, na który możesz głosować, a jeśli będzie wystarczająco dużo głosów, zostanie zaimplementowane.

12

Zmiana metody na PATCH nie zmienia zachowania Web API w żaden sposób. Nie ma wbudowanego mechanizmu wykonywania częściowych aktualizacji. Jednym z powodów, dla których tak długo nie było metody PATCH, jest brak wszechobecnego rodzaju nośnika do nakładania łat na zasoby.

Po drugie, pytasz Web API, aby wykonać serializację obiektów, więc nie ma takiej koncepcji stosowania częściowo zaktualizowanego obiektu. Byłoby tyle konwencji, aby się zgodzić, co oznacza wartość pusta, co z pustą wartością, jak mam powiedzieć "nie aktualizuj tego DateTime". A co z obiektami powiązanymi, przedmiotami podrzędnymi? Jak spowodować usunięcie elementu podrzędnego? O ile zespół CLR nie wdroży jakiejś koncepcji typu, który zawiera tylko podzbiór członków innego typu, częściowe aktualizacje i serializacja obiektów nie pójdą dobrze razem.

Aliostad wspomina o UpdateModel i jest to możliwe podczas aktualizacji z formularza HTML, ponieważ typ nośnika application/x-www-form-urlencoded jawnie zezwala na arbitralny zestaw par wartości nazwy. Nie ma "serializacji obiektów". Jest to tylko dopasowanie nazw z dopasowywanego formularza do nazw w obiekcie Model.

Dla siebie stworzyłem nowy typ mediów, którego używam do wykonywania częściowych aktualizacji, które działają jak formularz, ale są bardziej zaawansowane, ponieważ mogą obsługiwać dane hierarchiczne i zachowują kolejność aktualizacji.

+0

+1. Czy ten formatator twojego rodzaju mediów może być zawarty w api contrib w sieci? Jest to typowy scenariusz i mogę sobie wyobrazić, że taka funkcja jest często wymagana. – Aliostad

+0

Dziękuję za odpowiedź, jakie byłoby właściwe podejście, gdybym chciał zaktualizować tylko jedno pole mojego modelu (pole "zakończone" w tym scenariuszu)? Czy powinienem zrezygnować z interfejsu API? jak mogę to zrobić bez utraty zatwierdzenia modelu? Trudno uwierzyć, że tak prosta akcja nie byłaby możliwa dzięki "zaległościom" w technologii asp.net –

+0

Zmieniłem moje pytanie, aby lepiej opisać problem. –

0

Do mojego projektu użyłem Microsoft.AspNet.WebApi.OData i miałem problemy z pracą z JSON (praca z liczbami w moim przypadku). Ponadto pakiet OData ma pewne zależności, które z mojego punktu widzenia są zbyt duże dla pojedynczej funkcji (~ 7 MB ze wszystkimi zależnościami).

Więc opracowałem prostą bibliotekę, która robi to, o co prosisz: SimplePatch.

Jak korzystać

Zainstaluj pakiet używając:

Install-Package SimplePatch 

Następnie w kontrolerze:

[HttpPatch] 
public IHttpActionResult PatchOne(Delta<Todo> todo) 
{ 
    if (todo.TryGetPropertyValue(nameof(Todo.id), out int id)) { 
     // Entity to update (from your datasource) 
     var todoToPatch = Todos.FirstOrDefault(x => x.id == id); 
     if (todoToPatch == null) return BadRequest("Todo not found"); 

     todo.Patch(todoToPatch);  

     // Now todoToPatch is updated with new values    
    } else { 
     return BadRequest(); 
    }  

    return Ok(); 
} 

Biblioteka wsparcie masywny łata TOO:

[HttpPatch] 
public IHttpActionResult PatchMultiple(DeltaCollection<Todo> todos) 
{ 
    foreach (var todo in todos) 
    { 
     if (todo.TryGetPropertyValue(nameof(Todo.id), out int id)) 
     { 
      // Entity to update (from your datasource) 
      var entityToPatch = Todos.FirstOrDefault(x => x.id == Convert.ToInt32(id)); 
      if (entityToPatch == null) return BadRequest("Todo not found (Id = " + id + ")"); 

      person.Patch(entityToPatch); 
     } 
     else 
     { 
      return BadRequest("Id property not found for a todo"); 
     } 
    } 

    return Ok(); 
} 

Jeśli używasz Entity Framework, trzeba dodać tylko dwie linie kodu po wywołaniu metody Patch:

entity.Patch(entityToPatch); 

dbContext.Entry(entityToPatch).State = EntityState.Modified; 
dbContext.SaveChanges(); 

Ponadto, można wykluczyć niektóre właściwości mają być aktualizowane, gdy metoda Patch nazywa. Global.asax lub Startup.cs

DeltaConfig.Init((cfg) => 
{ 
    cfg.ExcludeProperties<Todo>(x => x.id); 
}); 

Jest to przydatne podczas pracy z podmiotem i nie chcesz, aby stworzyć model.