2012-04-26 28 views
16

Giả sử tôi có mô hình nàyasp web api vá thực hiện

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

Và tôi gửi thông điệp này như dữ liệu json để điều khiển tôi như là một yêu cầu bản vá. Đây thực sự là hành động lật đổ một hộp kiểm. Tôi nghĩ rằng nó làm cho sence mà tôi chỉ muốn gửi cho máy chủ của tôi, và không phải là toàn bộ mô hình.

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

Trình điều khiển WebApi của tôi cần phải trông như thế nào để xử lý đúng yêu cầu vá đơn giản, json này? Tôi có nên sử dụng api web cho điều này, hoặc tôi nên sử dụng một cách tiếp cận theo kiểu rpc hơn với mvc?

Có vẻ như một điều rất cơ bản cần làm, nhưng tôi dường như không thể làm đúng! Tôi nghĩ rằng tôi có thể cần phải sử dụng một tham số khác nhau trong phương pháp điều khiển của tôi, nhưng tôi không chắc chắn.

Cảm ơn bạn đã dành thời gian.

+0

Bạn có thể sử dụng JsonPatch được ASP.NET, ASP.NET Core và PCL hỗ trợ cho Xamarin. https://github.com/KevinDockx/JsonPatch. Bạn có thể tìm thấy bài viết hay tại đây http://benfoster.io/blog/aspnet-core-json-patch-partial-api-updates –

+0

Đó là một vấn đề khác mà tôi nghĩ. Mô hình của tôi không dựa trên json. Việc cập nhật trạng thái thực tế sẽ xảy ra như thế nào tùy thuộc vào người thực hiện. Tôi không muốn dịch một số thông số RFC thành một biến thể truy vấn SQL hoặc các thực thể. –

Trả lời

11

Bạn có thể tìm thấy tính năng PATCH trong gói Nuget trước khi phát hành OData: Microsoft.AspNet.WebApi.OData.

Thông tin về cách bạn có thể sử dụng để tạo hành động xử lý PATCH có thể được tìm thấy trong phần Cập nhật một phần (yêu cầu PATCH) của bài đăng trên blog về OData support in ASP.NET Web API.

+1

Nhìn vào mẫu này để thực hiện các bản vá thông qua json.net serializer mà không phụ thuộc vào định dạng dây oData - https: //aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/DeltaJsonDeserialization/ –

1

ASP.NET Web API có vẻ là thiếu UpdateModel, TryUpdateModel vv

Trong ASP.NET MVC, bạn có thể sử dụng chúng để đạt được hiệu quả mong muốn. Tôi đã tạo ra một work item trong ASP.NET Web Stack mà bạn có thể bỏ phiếu và nếu nó có đủ số phiếu bầu, nó sẽ được thực hiện.

12

Thay đổi phương thức thành PATCH không thay đổi hành vi của API Web theo bất kỳ cách nào. Không có cơ chế dựng sẵn để thực hiện cập nhật một phần. Một trong những lý do không có phương pháp PATCH quá lâu là không có loại phương tiện truyền thông phổ biến nào để áp dụng các bản vá lỗi cho các tài nguyên.

Thứ hai, bạn đang yêu cầu API Web thực hiện tuần tự hóa đối tượng cho bạn để không có khái niệm như vậy về việc áp dụng một đối tượng được cập nhật một phần. Sẽ có rất nhiều quy ước để đồng ý, giá trị rỗng có nghĩa là gì, giá trị rỗng, làm thế nào để tôi nói "không cập nhật DateTime này". Điều gì về các đối tượng liên quan, các mục con? Làm thế nào để bạn gây ra một mục con bị xóa? Trừ khi nhóm CLR triển khai một số khái niệm về một loại chỉ chứa một tập con của các thành viên từ một kiểu khác, các cập nhật từng phần và tuần tự hóa đối tượng sẽ không đi cùng nhau tốt.

Aliostad đề cập đến UpdateModel và điều đó có thể xảy ra khi cập nhật từ biểu mẫu HTML vì loại phương tiện application/x-www-form-urlencoded cho phép rõ ràng một bộ giá trị tên tùy ý. Không có "serialization đối tượng" đang diễn ra. Nó chỉ là một kết hợp của các tên từ biểu mẫu được so khớp với các tên trên đối tượng Model. Đối với bản thân mình, tôi đã tạo một loại phương tiện mới mà tôi sử dụng để thực hiện cập nhật từng phần hoạt động như biểu mẫu nhưng nâng cao hơn ở chỗ nó có thể xử lý dữ liệu phân cấp và duy trì thứ tự cập nhật.

+0

+1. Loại định dạng phương tiện truyền thông này của bạn có được bao gồm trong trang web api contrib không? Đây là một kịch bản phổ biến và tôi có thể tưởng tượng tính năng như vậy thường được yêu cầu. – Aliostad

+0

Cảm ơn câu trả lời của bạn, đây sẽ là phương pháp phù hợp nếu tôi muốn cập nhật chỉ một trường của mô hình của tôi (trường 'hoàn thành' trong trường hợp này)? Tôi có nên từ bỏ api trên web không? làm thế nào tôi có thể làm điều này mà không làm mất xác nhận mô hình của tôi? Thật khó để tin rằng một hành động đơn giản như vậy sẽ không thể thực hiện được với "những latests của latests" trong công nghệ asp.net –

+0

Tôi đã chỉnh sửa câu hỏi của mình để mô tả tốt hơn vấn đề. –

0

Tôi đã sử dụng Microsoft.AspNet.WebApi.OData cho dự án của mình và tôi đã gặp một số vấn đề khi làm việc với JSON (làm việc với các con số trong trường hợp của tôi). Ngoài ra, gói OData có một số phụ thuộc, theo quan điểm của tôi, là quá lớn đối với một tính năng đơn lẻ (~ 7MB với tất cả các phụ thuộc).

Vì vậy, tôi đã phát triển một thư viện đơn giản làm những gì bạn đang yêu cầu: SimplePatch.

Làm thế nào để sử dụng

Cài đặt gói sử dụng:

Install-Package SimplePatch 

Sau đó, trong điều khiển của bạn:

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

Thư viện hỗ trợ vá lớn quá:

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

Nếu bạn sử dụng Entity Framework, bạn phải thêm chỉ có hai dòng mã sau khi cuộc gọi đến phương pháp Patch:

entity.Patch(entityToPatch); 

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

Hơn nữa, bạn có thể loại trừ một số đặc tính được cập nhật khi các phương pháp Patch được gọi. Global.asax hoặc Startup.cs

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

này rất hữu ích khi bạn đang làm việc với một thực thể và bạn không muốn tạo ra một mô hình.

Các vấn đề liên quan