ASP.NET Core web apı 'sinde jsonpatch

, Tom Dykstra ve Kirk larkabağı tarafından

bu makalede, ASP.NET Core web apı 'sinde JSON Patch isteklerinin nasıl işleneceği açıklanır.

Paket yüklemesi

Uygulamanızda JSON yama desteğini etkinleştirmek için aşağıdaki adımları izleyin:

  1. Microsoft.AspNetCore.Mvc.NewtonsoftJsonNuGet paketini yükler.

  2. Startup.ConfigureServicesÇağırmak için projenin metodunu güncelleştirin AddNewtonsoftJson . Örnek:

    services
        .AddControllersWithViews()
        .AddNewtonsoftJson();
    

AddNewtonsoftJson , MVC hizmeti kayıt yöntemleriyle uyumludur:

JSON Patch, AddNewtonsoftJson ve System.Text.Js

AddNewtonsoftJson``System.Text.Json Tüm JSON içeriğini biçimlendirmek için kullanılan tabanlı giriş ve çıkış biçimlerini değiştirir. Kullanarak JSON Patch desteği eklemek için Newtonsoft.Json , diğer biçimleri değişmeden bırakarak, projenin Startup.ConfigureServices yöntemini aşağıdaki gibi güncelleştirin:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
    {
        options.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
    });
}

private static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter()
{
    var builder = new ServiceCollection()
        .AddLogging()
        .AddMvc()
        .AddNewtonsoftJson()
        .Services.BuildServiceProvider();

    return builder
        .GetRequiredService<IOptions<MvcOptions>>()
        .Value
        .InputFormatters
        .OfType<NewtonsoftJsonPatchInputFormatter>()
        .First();
}

Yukarıdaki kod, Microsoft.AspNetCore.Mvc.NewtonsoftJson paketi ve aşağıdaki using deyimlerini gerektirir:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Linq;

Newtonsoft.Json.JsonConvert.SerializeObjectBir JsonPatchDocument seri hale getirmek için yöntemini kullanın.

PATCH HTTP istek yöntemi

PUT ve Patch yöntemleri, var olan bir kaynağı güncelleştirmek için kullanılır. Bunlar arasındaki fark, PUT 'ın tüm kaynağı değiştirmesi, ancak düzeltme eki yalnızca değişiklikleri belirttiğinde.

JSON yaması

JSON yaması , bir kaynağa uygulanacak güncelleştirmelerin belirtilmesine yönelik bir biçimdir. JSON yama belgesinde bir dizi işlem vardır. Her işlem belirli bir değişiklik türünü tanımlar. Bu tür değişikliklere örnek olarak bir dizi öğesi ekleme veya bir özellik değeri değiştirme sayılabilir.

Örneğin, aşağıdaki JSON belgeleri bir kaynağı, kaynak için bir JSON yama belgesini ve düzeltme eki işlemlerini uygulamanın sonucunu temsil eder.

Kaynak örneği

{
  "customerName": "John",
  "orders": [
    {
      "orderName": "Order0",
      "orderType": null
    },
    {
      "orderName": "Order1",
      "orderType": null
    }
  ]
}

JSON Patch örneği

[
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "add",
    "path": "/orders/-",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Yukarıdaki JSON kodunda:

  • opÖzelliği, işlem türünü gösterir.
  • pathÖzelliği güncelleştirilecek öğeyi gösterir.
  • valueÖzelliği yeni değeri sağlar.

Düzeltme ekiyle sonra kaynak

Önceki JSON Patch belgesi uygulandıktan sonra kaynak şu şekildedir:

{
  "customerName": "Barry",
  "orders": [
    {
      "orderName": "Order0",
      "orderType": null
    },
    {
      "orderName": "Order1",
      "orderType": null
    },
    {
      "orderName": "Order2",
      "orderType": null
    }
  ]
}

Bir kaynak için bir JSON Patch belgesi uygulanarak yapılan değişiklikler atomik. Listedeki herhangi bir işlem başarısız olursa, listede hiçbir işlem uygulanmaz.

Yol sözdizimi

Bir işlem nesnesinin Path özelliği düzeyler arasında eğik çizgi içeriyor. Örneğin, "/address/zipCode".

Sıfır tabanlı dizinler, dizi öğelerini belirtmek için kullanılır. Dizinin ilk öğesi addresses /addresses/0 . addBir dizinin sonuna kadar, - Dizin numarası yerine bir tire () kullanın: /addresses/- .

Operations

Aşağıdaki tabloda, JSON Patch belirtimindetanımlanan desteklenen işlemler gösterilmektedir:

İşlem Notlar
add Bir özellik veya dizi öğesi ekleyin. Var olan özellik için: set değeri.
remove Bir özellik veya dizi öğesi kaldırın.
replace Aynı remove konumdaki ve sonrasında aynı add .
move Kaynaktaki remove add değeri kullanarak kaynağından sonra hedefle aynı.
copy addKaynaktaki değeri kullanarak hedefle aynı olacak şekilde aynı.
test Değer: belirtilmişse başarı durum kodu döndürür path value .

ASP.NET Core JSON yaması

JSON düzeltme ekinin ASP.NET Core uygulanması Microsoft.AspNetCore.Jsonpatch NuGet paketinde sunulmaktadır.

Eylem yöntemi kodu

Bir API denetleyicisinde, JSON yaması için bir eylem yöntemi:

  • , Özniteliğiyle açıklama eklenir HttpPatch .
  • JsonPatchDocument<T>, Genellikle ile kabul eder [FromBody] .
  • ApplyToDeğişiklikleri uygulamak için düzeltme eki belgesindeki çağrılar.

Aşağıda bir örnek verilmiştir:

[HttpPatch]
public IActionResult JsonPatchWithModelState(
    [FromBody] JsonPatchDocument<Customer> patchDoc)
{
    if (patchDoc != null)
    {
        var customer = CreateCustomer();

        patchDoc.ApplyTo(customer, ModelState);

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        return new ObjectResult(customer);
    }
    else
    {
        return BadRequest(ModelState);
    }
}

Örnek uygulamadaki Bu kod aşağıdaki modelle birlikte kullanılabilir Customer :

public class Customer
{
    public string CustomerName { get; set; }
    public List<Order> Orders { get; set; }
}
public class Order
{
    public string OrderName { get; set; }
    public string OrderType { get; set; }
}

Örnek eylem yöntemi:

  • Bir oluşturur Customer .
  • Düzeltme ekini uygular.
  • Yanıtın gövdesinde sonucu döndürür.

Gerçek bir uygulamada, kod veritabanı gibi bir mağazadan verileri alır ve düzeltme ekini uyguladıktan sonra veritabanını güncelleştirir.

Model durumu

Önceki eylem yöntemi örneği, ApplyTo parametrelerinden biri olarak model durumunu alan aşırı yüklemesini çağırır. Bu seçenekle, yanıtlardan hata iletileri alabilirsiniz. Aşağıdaki örnekte bir işlem için 400 Hatalı Istek yanıtının gövdesi gösterilmektedir test :

{
    "Customer": [
        "The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
    ]
}

Dinamik nesneler

Aşağıdaki eylem yöntemi örneği, dinamik bir nesneye nasıl düzeltme eki uygulanacağını gösterir:

[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
    dynamic obj = new ExpandoObject();
    patch.ApplyTo(obj);

    return Ok(obj);
}

Ekleme işlemi

  • pathBir dizi öğesine işaret ediyorsa: tarafından belirtiden önce yeni bir öğe ekler path .
  • pathBir özelliğe işaret ediyorsa: özellik değerini ayarlar.
  • pathVarolmayan bir konuma işaret ediyorsa:
    • Yama yapılacak kaynak dinamik bir nesnedir: bir özellik ekler.
    • Yama yapılacak kaynak statik bir nesnese: istek başarısız olur.

Aşağıdaki örnek düzeltme eki belgesi değerini ayarlar CustomerName ve Order dizinin sonuna bir nesnesi ekler Orders .

[
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "add",
    "path": "/orders/-",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Kaldırma işlemi

  • pathBir dizi öğesine işaret ediyorsa: öğesini kaldırır.
  • pathBir özelliğe işaret ediyorsa:
    • Yayama kaynağı dinamik bir nesne ise: özelliğini kaldırır.
    • Yama yapılacak kaynak statik bir nesnese:
      • Özellik null atanabilir ise: null olarak ayarlar.
      • Özellik null atanamaz ise, olarak ayarlar default<T> .

Aşağıdaki örnek düzeltme eki belgesi CustomerName null ve siler olarak ayarlanır Orders[0] :

[
  {
    "op": "remove",
    "path": "/customerName"
  },
  {
    "op": "remove",
    "path": "/orders/0"
  }
]

Değiştirme işlemi

Bu işlem, bir remove sonrasında bir ile aynıdır add .

Aşağıdaki örnek düzeltme eki belgesi değerini ayarlar CustomerName ve Orders[0] Yeni bir Order nesneyle değiştirir:

[
  {
    "op": "replace",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "replace",
    "path": "/orders/0",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Taşıma işlemi

  • pathBir dizi öğesinin işaret ediyorsa: öğesini öğesinin from konumuna kopyalar path , sonra remove öğesi üzerinde bir işlem çalıştırır from .
  • pathBir özelliğe işaret ediyorsa: özelliğin değerini özelliğine kopyalar from path ve sonra remove özelliği üzerinde bir işlem çalıştırır from .
  • pathVarolmayan bir özelliğe işaret ediyorsa:
    • Yama yapılacak kaynak statik bir nesnese: istek başarısız olur.
    • Yaması gereken kaynak dinamik bir nesnedir: from özelliği tarafından belirtilen konuma kopyalar path , sonra remove özellik üzerinde bir işlem çalıştırır from .

Aşağıdaki örnek düzeltme eki belgesi:

  • Değerini Orders[0].OrderName olarak kopyalar CustomerName .
  • Orders[0].OrderNameNull olarak ayarlar.
  • Orders[1]Öncesine gider Orders[0] .
[
  {
    "op": "move",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "move",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Kopyalama işlemi

Bu işlem, son adım olmadan bir move işlemle işlevsel olarak remove aynıdır.

Aşağıdaki örnek düzeltme eki belgesi:

  • değerini değerine Orders[0].OrderName CustomerName kopyalar.
  • önce bir kopyasını Orders[1] Orders[0] ekler.
[
  {
    "op": "copy",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "copy",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Test işlemi

tarafından belirtilen konumdaki değer içinde sağlanan değerden farklı path ise istek başarısız value olur. Bu durumda, yama belgesinde diğer tüm işlemler başarılı olsa bile PATCH isteğinin tamamı başarısız olur.

İşlem test genellikle eşzamanlılık çakışması olduğunda bir güncelleştirmeyi önlemek için kullanılır.

Aşağıdaki örnek düzeltme eki belgesinin ilk değeri "John" ise hiçbir etkisi CustomerName yoktur çünkü test başarısız olur:

[
  {
    "op": "test",
    "path": "/customerName",
    "value": "Nancy"
  },
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  }
]

Kodu alma

Örnek kodu görüntüleme veya indirme. (İndirme).

Örneği test etmek için uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri gönderin:

  • Url: http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
  • HTTP yöntemi: PATCH
  • Üstbilgi: Content-Type: application/json-patch+json
  • Gövde: JSON proje klasöründeki JSON düzeltme eki belge örneklerinden birini kopyalayıp yapıştırın.

Ek kaynaklar

Bu makalede, bir web API'sinde JSON Patch isteklerini ASP.NET Core açıklanmıştır.

PATCH HTTP isteği yöntemi

PUT ve PATCH yöntemleri, mevcut bir kaynağı güncelleştirmek için kullanılır. Aralarındaki fark PUT'ın kaynağın tamamını değiştirmesi, PATCH ise yalnızca değişiklikleri belirtir.

JSON Düzeltme Eki

JSON Patch, bir kaynağa uygulanacak güncelleştirmeleri belirtme biçimidir. JSON Patch belgesi bir dizi işlem içerir. Her işlem, dizi öğesi ekleme veya bir özellik değerini değiştirme gibi belirli bir değişiklik türünü tanımlar.

Örneğin, aşağıdaki JSON belgeleri bir kaynağı, kaynak için bir JSON düzeltme eki belgesini ve düzeltme eki işlemlerinin uygulanmasına yönelik sonucu temsil ediyor.

Kaynak örneği

{
  "customerName": "John",
  "orders": [
    {
      "orderName": "Order0",
      "orderType": null
    },
    {
      "orderName": "Order1",
      "orderType": null
    }
  ]
}

JSON düzeltme eki örneği

[
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "add",
    "path": "/orders/-",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Yukarıdaki JSON kodunda:

  • opözelliği, işlem türünü gösterir.
  • özelliği, path güncelleştirilen öğeyi gösterir.
  • özelliği value yeni değeri sağlar.

Düzeltme eki sonrası kaynak

Önceki JSON Düzeltme Eki belgesini uygulamadan sonraki kaynak şu şekildedir:

{
  "customerName": "Barry",
  "orders": [
    {
      "orderName": "Order0",
      "orderType": null
    },
    {
      "orderName": "Order1",
      "orderType": null
    },
    {
      "orderName": "Order2",
      "orderType": null
    }
  ]
}

Bir kaynağa JSON Düzeltme Eki belgesi uygulanarak yapılan değişiklikler atomiktir: listede herhangi bir işlem başarısız olursa, listede hiçbir işlem uygulanmaz.

Yol söz dizimi

Bir işlem nesnesinin path özelliği, düzeyler arasında eğik çizgi içerir. Örneğin, "/address/zipCode".

Dizi öğelerini belirtmek için sıfır tabanlı dizinler kullanılır. Dizinin ilk öğesi addresses /addresses/0 şudur: . Bir add dizinin sonuna bir dizin numarası yerine kısa çizgi (-) kullanın: /addresses/- .

Operations

Aşağıdaki tabloda, JSONDüzeltme Eki belirtimsinde tanımlanan desteklenen işlemler yer alır:

İşlem Notlar
add Özellik veya dizi öğesi ekleyin. Mevcut özellik için: değeri ayarlayın.
remove Bir özelliği veya dizi öğesini kaldırın.
replace Takip remove ettiği add konumla aynı.
move Kaynaktan gelen remove değeri kullanarak kaynaktan sonra hedefe kadar add olanlarla aynı.
copy Kaynaktan değer add kullanan hedefle aynı.
test değeri = sağlandı ise başarı path durumu kodunu geri value dönme.

ASP.NET Core'de JsonPatch

JSON ASP.NET Core uygulama, Microsoft.AspNetCore.JsonPatch NuGet sağlanır. Paket, meta Microsoft.AspnetCore.App dahil edilir.

Eylem yöntemi kodu

API denetleyicisinde JSON Patch için bir eylem yöntemi:

  • özniteliğiyle açıklama HttpPatch ek açıklamalıdır.
  • , genellikle JsonPatchDocument<T> ile kabul [FromBody] eder.
  • Değişiklikleri ApplyTo uygulamak için yama belgesine çağrılar.

Aşağıda bir örnek verilmiştir:

[HttpPatch]
public IActionResult JsonPatchWithModelState(
    [FromBody] JsonPatchDocument<Customer> patchDoc)
{
    if (patchDoc != null)
    {
        var customer = CreateCustomer();

        patchDoc.ApplyTo(customer, ModelState);

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        return new ObjectResult(customer);
    }
    else
    {
        return BadRequest(ModelState);
    }
}

Örnek uygulamanın bu kodu aşağıdaki modelle Customer çalışır.

public class Customer
{
    public string CustomerName { get; set; }
    public List<Order> Orders { get; set; }
}
public class Order
{
    public string OrderName { get; set; }
    public string OrderType { get; set; }
}

Örnek eylem yöntemi:

  • bir Customer yapısındadır.
  • Düzeltme ekini uygular.
  • Yanıtın gövdesinde sonucu döndürür.

Gerçek bir uygulamada kod, verileri veritabanı gibi bir depodan alır ve düzeltme ekini uygulamaya başladıktan sonra veritabanını güncelleştirer.

Model durumu

Yukarıdaki eylem yöntemi örneği, parametrelerinden biri ApplyTo olarak model durumunu alan bir aşırı yüklemesini çağırıyor. Bu seçenekle, yanıtlarda hata iletileri alabilirsiniz. Aşağıdaki örnek, bir işlem için 400 Hatalı İstek yanıtının gövdesini test gösterir:

{
    "Customer": [
        "The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
    ]
}

Dinamik nesneler

Aşağıdaki eylem yöntemi örneğinde, dinamik bir nesneye düzeltme eki uygulama işlemi gösterir.

[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
    dynamic obj = new ExpandoObject();
    patch.ApplyTo(obj);

    return Ok(obj);
}

Ekleme işlemi

  • Bir path dizi öğesini gösterirse: tarafından belirtilen öğeden önce yeni öğe path ekler.
  • Bir path özelliğin değerinin yer alıyorsa: özellik değerini ayarlar.
  • Var path olan bir konumun yeri ise:
    • Düzeltme eki uygulama kaynağı dinamik bir nesne ise: bir özellik ekler.
    • Düzeltme eki uygulama kaynağı statik bir nesne ise istek başarısız olur.

Aşağıdaki örnek düzeltme eki belgesi değerini ayarlar CustomerName ve Order dizisinin sonuna bir nesnesi Orders ekler.

[
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "add",
    "path": "/orders/-",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Kaldırma işlemi

  • Bir path dizi öğesini işaret ediyorsa: öğesini kaldırır.
  • Bir path özelliğin noktası ise:
    • Düzeltme eki uygulama kaynağı dinamik bir nesne ise: özelliğini kaldırır.
    • Düzeltme eki uygulama kaynağı statik bir nesne ise:
      • Özellik null değere sahipse: null olarak ayarlar.
      • Özelliği null değere sahip olmayan bir özellik olarak default<T> ayarlar.

Aşağıdaki örnek düzeltme eki belgesi CustomerName null olarak ayarlanır ve Orders[0] siler.

[
  {
    "op": "remove",
    "path": "/customerName"
  },
  {
    "op": "remove",
    "path": "/orders/0"
  }
]

Değiştirme işlemi

Bu işlem işlevsel olarak ile ve ardından remove bir ile add aynıdır.

Aşağıdaki örnek düzeltme eki belgesi değerini ayarlar CustomerName ve değerini yeni bir Orders[0] nesneyle Order değiştirir.

[
  {
    "op": "replace",
    "path": "/customerName",
    "value": "Barry"
  },
  {
    "op": "replace",
    "path": "/orders/0",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

Taşıma işlemi

  • pathBir dizi öğesinin işaret ediyorsa: öğesini öğesinin from konumuna kopyalar path , sonra remove öğesi üzerinde bir işlem çalıştırır from .
  • pathBir özelliğe işaret ediyorsa: özelliğin değerini özelliğine kopyalar from path ve sonra remove özelliği üzerinde bir işlem çalıştırır from .
  • pathVarolmayan bir özelliğe işaret ediyorsa:
    • Yama yapılacak kaynak statik bir nesnese: istek başarısız olur.
    • Yaması gereken kaynak dinamik bir nesnedir: from özelliği tarafından belirtilen konuma kopyalar path , sonra remove özellik üzerinde bir işlem çalıştırır from .

Aşağıdaki örnek düzeltme eki belgesi:

  • Değerini Orders[0].OrderName olarak kopyalar CustomerName .
  • Orders[0].OrderNameNull olarak ayarlar.
  • Orders[1]Öncesine gider Orders[0] .
[
  {
    "op": "move",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "move",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Kopyalama işlemi

Bu işlem, move son adım olmadan işlem ile aynı şekilde aynıdır remove .

Aşağıdaki örnek düzeltme eki belgesi:

  • Değerini Orders[0].OrderName olarak kopyalar CustomerName .
  • Daha önce bir kopyası Orders[1] ekler Orders[0] .
[
  {
    "op": "copy",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "copy",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Test işlemi

Tarafından belirtilen konumdaki değer path içinde belirtilen değerden farklıysa value , istek başarısız olur. Bu durumda, yama belgesindeki diğer tüm işlemler başka bir şekilde başarılı olsa bile, tüm yama isteği başarısız olur.

İşlem, bir test eşzamanlılık çakışması olduğunda bir güncelleştirmeyi engellemek için yaygın olarak kullanılır.

Aşağıdaki örnek düzeltme eki belgesinin ilk değeri CustomerName "John" ise, test başarısız olursa hiçbir etkisi yoktur:

[
  {
    "op": "test",
    "path": "/customerName",
    "value": "Nancy"
  },
  {
    "op": "add",
    "path": "/customerName",
    "value": "Barry"
  }
]

Kodu alma

Örnek kodu görüntüleyin veya indirin. (İndirme).

Örneği test etmek için, uygulamayı çalıştırın ve aşağıdaki ayarlarla HTTP istekleri gönderin:

  • 'DEKI http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
  • HTTP yöntemi: PATCH
  • Üst bilgi Content-Type: application/json-patch+json
  • Gövde: JSON proje klasöründen JSON Patch belgesi örneklerinden birini kopyalayıp yapıştırın.

Ek kaynaklar