Freigeben über


JSON-Patchunterstützung in ASP.NET Core-Web-API

In diesem Artikel wird erläutert, wie JSON Patch-Anforderungen in einer ASP.NET Core-Web-API behandelt werden.

Die Unterstützung von JSON Patch in ASP.NET Core-Web-API basiert auf der System.Text.Json-Serialisierung und erfordert das Microsoft.AspNetCore.JsonPatch.SystemTextJson-NuGet-Paket.

Was ist der JSON-Patchstandard?

Der JSON-Patchstandard:

  • Ist ein Standardformat zum Beschreiben von Änderungen, die auf ein JSON-Dokument angewendet werden sollen.

  • Ist in RFC 6902 definiert und wird in RESTful-APIs häufig verwendet, um partielle Aktualisierungen an JSON-Ressourcen durchzuführen.

  • Beschreibt eine Abfolge von Vorgängen, die ein JSON-Dokument ändern, z. B.:

    • add
    • remove
    • replace
    • move
    • copy
    • test

In Web-Apps wird JSON Patch häufig in einem PATCH-Vorgang verwendet, um partielle Aktualisierungen einer Ressource auszuführen. Anstatt die gesamte Ressource für ein Update zu senden, können Clients ein JSON-Patchdokument senden, das nur die Änderungen enthält. Reparieren reduziert die Ladungsgröße und verbessert die Effizienz.

Eine Übersicht über den JSON-Patchstandard finden Sie unter jsonpatch.com.

JSON-Patchunterstützung in ASP.NET Core-Web-API

JSON Patch-Support in der ASP.NET Core-Web-API basiert auf „System.Text.Json“-Serialisierung, beginnend mit .NET 10, und implementiert „Microsoft.AspNetCore.JsonPatch“ basierend auf „System.Text.Json“-Serialisierung. Mithilfe dieser Funktion

Hinweis

Die Implementierung von Microsoft.AspNetCore.JsonPatch basierend auf der Serialisierung von System.Text.Json ist kein direkter Ersatz für die Vorgänger-Implementierung, die auf Newtonsoft.Json basiert. Es unterstützt keine dynamischen Typen, z. B. ExpandoObject.

Von Bedeutung

Der JSON Patch-Standard hat inhärente Sicherheitsrisiken. Da diese Risiken dem JSON Patch-Standard inhärent sind, versucht die ASP.NET Core-Implementierung nicht, inhärente Sicherheitsrisiken zu mindern. Es liegt in der Verantwortung des Entwicklers, sicherzustellen, dass das JSON-Patchdokument sicher auf das Zielobjekt angewendet werden kann. Weitere Informationen finden Sie im Abschnitt "Minderung von Sicherheitsrisiken" .

Aktivieren der JSON-Patchunterstützung mit System.Text.Json

Um die JSON-Patchunterstützung mit System.Text.Jsonzu aktivieren, installieren Sie das Microsoft.AspNetCore.JsonPatch.SystemTextJson NuGet-Paket.

dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson --prerelease

Dieses Paket stellt eine JsonPatchDocument<TModel> Klasse bereit, um ein JSON Patch-Dokument für Objekte vom Typ T darzustellen und benutzerdefinierte Logik zum Serialisieren und Deserialisieren von JSON Patch-Dokumenten mithilfe von System.Text.Json bereitzustellen. Die Schlüsselmethode der JsonPatchDocument<TModel> Klasse ist ApplyTo(Object), die die Patchvorgänge auf ein Zielobjekt vom Typ Tanwendet.

Aktionsmethodencode, der JSON-Patch anwendet

Eine Aktionsmethode für JSON Patch in einem API-Controller:

Beispiel-Controlleraktionsmethode:

[HttpPatch("{id}", Name = "UpdateCustomer")]
public IActionResult Update(AppDb db, string id, [FromBody] JsonPatchDocument<Customer> patchDoc)
{
    // Retrieve the customer by ID
    var customer = db.Customers.FirstOrDefault(c => c.Id == id);

    // Return 404 Not Found if customer doesn't exist
    if (customer == null)
    {
        return NotFound();
    }

    patchDoc.ApplyTo(customer, jsonPatchError =>
        {
            var key = jsonPatchError.AffectedObject.GetType().Name;
            ModelState.AddModelError(key, jsonPatchError.ErrorMessage);
        }
    );

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

    return new ObjectResult(customer);
}

Dieser Code aus der Beispiel-App funktioniert mit den folgenden Customer und Order Modellen:

namespace App.Models;

public class Customer
{
    public string Id { get; set; }
    public string? Name { get; set; }
    public string? Email { get; set; }
    public string? PhoneNumber { get; set; }
    public string? Address { get; set; }
    public List<Order>? Orders { get; set; }

    public Customer()
    {
        Id = Guid.NewGuid().ToString();
    }
}
namespace App.Models;

public class Order
{
    public string Id { get; set; }
    public DateTime? OrderDate { get; set; }
    public DateTime? ShipDate { get; set; }
    public decimal TotalAmount { get; set; }

    public Order()
    {
        Id = Guid.NewGuid().ToString();
    }
}

Die wichtigsten Schritte der Beispielaktionsmethode:

  • Kunden abrufen:
    • Die Methode ruft ein Customer Objekt aus der Datenbank AppDb mithilfe der bereitgestellten ID ab.
    • Wenn kein Customer Objekt gefunden wird, wird eine 404 Not Found Antwort zurückgegeben.
  • JSON-Patch anwenden:
    • Die ApplyTo(Object) Methode wendet die JSON-Patchvorgänge aus dem patchDoc auf das abgerufene Customer Objekt an.
    • Wenn Während der Patchanwendung Fehler auftreten, z. B. ungültige Vorgänge oder Konflikte, werden sie von einem Fehlerbehandlungsdelegat erfasst. Dieser Delegat fügt dem ModelState Fehlermeldungen hinzu, indem er den Typnamen des betroffenen Objekts und die Fehlermeldung verwendet.
  • ModelState überprüfen:
    • Nachdem der Patch angewendet wurde, überprüft die Methode das ModelState auf Fehler.
    • Wenn dies ModelState ungültig ist, z. B. aufgrund von Patchfehlern, wird eine 400 Bad Request Antwort mit den Überprüfungsfehlern zurückgegeben.
  • Den aktualisierten Kunden zurückgeben:
    • Wenn der Patch erfolgreich angewendet wurde und ModelState gültig ist, gibt die Methode das aktualisierte Customer Objekt in der Antwort zurück.

Beispielfehlerantwort:

Das folgende Beispiel zeigt den Textkörper einer 400 Bad Request Antwort für einen JSON-Patchvorgang, wenn der angegebene Pfad ungültig ist:

{
  "Customer": [
    "The target location specified by path segment 'foobar' was not found."
  ]
}

Anwenden eines JSON-Patchdokuments auf ein Objekt

Die folgenden Beispiele veranschaulichen die Verwendung der ApplyTo(Object) Methode zum Anwenden eines JSON-Patchdokuments auf ein Objekt.

Beispiel: Anwenden eines Objekts JsonPatchDocument<TModel> auf ein Objekt

Dies wird im folgenden Beispiel veranschaulicht:

  • Die add, replaceund remove Vorgänge.
  • Operationen auf geschachtelten Eigenschaften.
  • Hinzufügen eines neuen Elements zu einem Array.
  • Verwendung eines Konverters für JSON-String-Enums in einem JSON-Patchdokument.
// Original object
var person = new Person {
    FirstName = "John",
    LastName = "Doe",
    Email = "johndoe@gmail.com",
    PhoneNumbers = [new() {Number = "123-456-7890", Type = PhoneNumberType.Mobile}],
    Address = new Address
    {
        Street = "123 Main St",
        City = "Anytown",
        State = "TX"
    }
};

// Raw JSON patch document
string jsonPatch = """
[
    { "op": "replace", "path": "/FirstName", "value": "Jane" },
    { "op": "remove", "path": "/Email"},
    { "op": "add", "path": "/Address/ZipCode", "value": "90210" },
    { "op": "add", "path": "/PhoneNumbers/-", "value": { "Number": "987-654-3210",
                                                                "Type": "Work" } }
]
""";

// Deserialize the JSON patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);

// Apply the JSON patch document
patchDoc!.ApplyTo(person);

// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));

Im vorherigen Beispiel wird die folgende Ausgabe des aktualisierten Objekts angezeigt:

{
    "firstName": "Jane",
    "lastName": "Doe",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "TX",
        "zipCode": "90210"
    },
    "phoneNumbers": [
        {
            "number": "123-456-7890",
            "type": "Mobile"
        },
        {
            "number": "987-654-3210",
            "type": "Work"
        }
    ]
}

Die ApplyTo(Object) Methode folgt in der Regel den Konventionen und Optionen System.Text.Json für die JsonPatchDocument<TModel>Verarbeitung, einschließlich des Verhaltens, das durch die folgenden Optionen gesteuert wird:

Wichtige Unterschiede zwischen System.Text.Json und der neuen JsonPatchDocument<TModel> Implementierung:

  • Der Laufzeittyp des Zielobjekts bestimmt, welche Eigenschaften ApplyTo(Object) gepatcht werden, nicht der deklarierte Typ.
  • System.Text.Json Deserialisierung basiert auf dem deklarierten Typ, um berechtigte Eigenschaften zu identifizieren.

Beispiel: Anwenden eines JsonPatchDocument mit Fehlerbehandlung

Es gibt verschiedene Fehler, die beim Anwenden eines JSON-Patchdokuments auftreten können. Das Zielobjekt kann beispielsweise nicht über die angegebene Eigenschaft verfügen, oder der angegebene Wert ist mit dem Eigenschaftstyp nicht kompatibel.

JSON Patch unterstützt den test Vorgang, der überprüft, ob ein angegebener Wert der Zieleigenschaft entspricht. Wenn dies nicht der Fall ist, wird ein Fehler zurückgegeben.

Im folgenden Beispiel wird veranschaulicht, wie diese Fehler ordnungsgemäß behandelt werden.

Von Bedeutung

Das an die ApplyTo(Object) Methode übergebene Objekt wird vor Ort geändert. Der Aufrufer ist für das Verwerfen von Änderungen verantwortlich, wenn ein Vorgang fehlschlägt.

// Original object
var person = new Person {
    FirstName = "John",
    LastName = "Doe",
    Email = "johndoe@gmail.com"
};

// Raw JSON patch document
string jsonPatch = """
[
    { "op": "replace", "path": "/Email", "value": "janedoe@gmail.com"},
    { "op": "test", "path": "/FirstName", "value": "Jane" },
    { "op": "replace", "path": "/LastName", "value": "Smith" }
]
""";

// Deserialize the JSON patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);

// Apply the JSON patch document, catching any errors
Dictionary<string, string[]>? errors = null;
patchDoc!.ApplyTo(person, jsonPatchError =>
    {
        errors ??= new ();
        var key = jsonPatchError.AffectedObject.GetType().Name;
        if (!errors.ContainsKey(key))
        {
            errors.Add(key, new string[] { });
        }
        errors[key] = errors[key].Append(jsonPatchError.ErrorMessage).ToArray();
    });
if (errors != null)
{
    // Print the errors
    foreach (var error in errors)
    {
        Console.WriteLine($"Error in {error.Key}: {string.Join(", ", error.Value)}");
    }
}

// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));

Das vorherige Beispiel führt zu folgender Ausgabe:

Error in Person: The current value 'John' at path 'FirstName' is not equal 
to the test value 'Jane'.
{
    "firstName": "John",
    "lastName": "Smith",              <<< Modified!
    "email": "janedoe@gmail.com",     <<< Modified!
    "phoneNumbers": []
}

Risikominderung bei der IT-Sicherheit

Bei der Verwendung des Microsoft.AspNetCore.JsonPatch.SystemTextJson Pakets ist es wichtig, potenzielle Sicherheitsrisiken zu verstehen und zu mindern. In den folgenden Abschnitten werden die identifizierten Sicherheitsrisiken im Zusammenhang mit JSON-Patch beschrieben und empfohlene Gegenmaßnahmen bereitgestellt, um die sichere Verwendung des Pakets sicherzustellen.

Von Bedeutung

Dies ist keine vollständige Liste der Bedrohungen. App-Entwickler müssen ihre eigenen Bedrohungsmodellüberprüfungen durchführen, um eine appspezifische umfassende Liste zu ermitteln und bei Bedarf geeignete Gegenmaßnahmen zu erstellen. Beispielsweise sollten Apps, die Sammlungen Patchvorgängen zur Verfügung stellen, das Potenzial für algorithmische Komplexitätsangriffe berücksichtigen, wenn diese Vorgänge Elemente am Anfang der Sammlung einfügen oder entfernen.

Um Sicherheitsrisiken beim Integrieren von JSON-Patchfunktionen in ihre Apps zu minimieren, sollten Entwickler:

  • Führen Sie umfassende Bedrohungsmodelle für ihre eigenen Apps aus.
  • Adressieren Sie identifizierte Bedrohungen.
  • Folgen Sie den empfohlenen Gegenmaßnahmen in den folgenden Abschnitten.

Denial of Service (DoS) über Speicherverstärkung

  • Szenario: Ein böswilliger Client sendet einen copy Vorgang, der große Objektdiagramme mehrmals dupliziert, was zu übermäßigem Arbeitsspeicherverbrauch führt.
  • Wirkung: Potenzielle nicht genügend Arbeitsspeicher-Bedingungen, die Dienstunterbrechungen verursachen.
  • Risikominderung:
    • Überprüfen Sie eingehende JSON Patch-Dokumente auf Größe und Struktur vor dem Aufrufen ApplyTo(Object).
    • Die Überprüfung muss appspezifisch sein, aber eine Beispielüberprüfung kann ähnlich wie folgt aussehen:
public void Validate(JsonPatchDocument<T> patch)
{
    // This is just an example. It's up to the developer to make sure that
    // this case is handled properly, based on the app needs.
    if (patch.Operations.Where(op=>op.OperationType == OperationType.Copy).Count()
                              > MaxCopyOperationsCount)
    {
        throw new InvalidOperationException();
    }
}

Geschäftslogik-Subversion

  • Szenario: Patchvorgänge können Felder mit impliziten Invarianten (z. B. interne Flags, IDs oder berechnete Felder) bearbeiten, um Geschäftseinschränkungen zu verletzen.
  • Auswirkung: Datenintegritätsprobleme und unbeabsichtigtes App-Verhalten.
  • Risikominderung:
    • Verwenden Sie POCOs (einfache alte CLR-Objekte) mit explizit definierten Eigenschaften, die sicher geändert werden können.
      • Vermeiden Sie das Verfügbarmachen vertraulicher oder sicherheitskritischer Eigenschaften im Zielobjekt.
      • Wenn ein POCO-Objekt nicht verwendet wird, überprüfen Sie das gepatchte Objekt nach dem Anwenden von Vorgängen, um sicherzustellen, dass Geschäftsregeln und Invarianten nicht verletzt werden.

Authentifizierung und Autorisierung

  • Szenario: Nicht authentifizierte oder nicht autorisierte Clients senden bösartige JSON-Patchanforderungen.
  • Auswirkung: Nicht autorisierter Zugriff, um vertrauliche Daten zu ändern oder das App-Verhalten zu stören.
  • Risikominderung:
    • Schützen Sie Endpunkte, die JSON-Patchanforderungen mit ordnungsgemäßen Authentifizierungs- und Autorisierungsmechanismen akzeptieren.
    • Einschränken des Zugriffs auf vertrauenswürdige Clients oder Benutzer mit entsprechenden Berechtigungen.

Abrufen des Codes

Ansicht oder herunterladen von Beispielcode. (Informationen zum Herunterladen)

Um das Beispiel zu testen, führen Sie die App aus, und senden Sie HTTP-Anforderungen mit den folgenden Einstellungen:

  • URL: http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
  • HTTP-Methode: PATCH
  • Header: Content-Type: application/json-patch+json
  • Text Kopieren und einfügen Sie eine der JSON-Reparaturdokument-Stichproben aus dem JSON-Projektordner.

Zusätzliche Ressourcen

In diesem Artikel wird erläutert, wie JSON Patch-Anforderungen in einer ASP.NET Core-Web-API behandelt werden.

Von Bedeutung

Der JSON Patch-Standard hat inhärente Sicherheitsrisiken. Diese Implementierung versucht nicht, diese inhärenten Sicherheitsrisiken zu mindern. Es liegt in der Verantwortung des Entwicklers, sicherzustellen, dass das JSON-Patchdokument sicher auf das Zielobjekt angewendet werden kann. Weitere Informationen finden Sie im Abschnitt "Minderung von Sicherheitsrisiken" .

Paketinstallation

JSON-Reparatur-Support in der ASP.NET Core-Web-API basiert auf „Newtonsoft.Json“ und erfordert das „Microsoft.AspNetCore.Mvc.NewtonsoftJson“-NuGet-Paket.

Um JSON-Reparieren-Support zu aktivieren:

  • Installieren Sie das Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet-Paket.

  • Rufen Sie AddNewtonsoftJson auf. Zum Beispiel:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllers()
        .AddNewtonsoftJson();
    
    var app = builder.Build();
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    

AddNewtonsoftJson ersetzt die Standard-System.Text.Json-basierten Eingabe/Ausgabe-Formatierer, die zur Formatierung aller JSON-Inhalte verwendet werden. Diese Erweiterungsmethode ist mit den folgenden MVC-Dienstregistrierungsmethoden kompatibel:

JsonPatch erfordert das Festlegen des Content-Type-Headers auf application/json-patch+json.

Hinzufügen von Support für JSON-Reparieren bei der Verwendung von System.Text.Json

Der auf System.Text.Json-basierte Eingabeformatierer unterstützt JSON Patch nicht. Hinzufügen von Support für JSON Patch unter Verwendung von „Newtonsoft.Json“, während die anderen Eingabe- und Ausgabeformatierer unverändert bleiben:

  • Installieren Sie das Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet-Paket.

  • Aktualisieren Sie Program.cs:

    using JsonPatchSample;
    using Microsoft.AspNetCore.Mvc.Formatters;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllers(options =>
    {
        options.InputFormatters.Insert(0, MyJPIF.GetJsonPatchInputFormatter());
    });
    
    var app = builder.Build();
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Formatters;
    using Microsoft.Extensions.Options;
    
    namespace JsonPatchSample;
    
    public static class MyJPIF
    {
        public static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter()
        {
            var builder = new ServiceCollection()
                .AddLogging()
                .AddMvc()
                .AddNewtonsoftJson()
                .Services.BuildServiceProvider();
    
            return builder
                .GetRequiredService<IOptions<MvcOptions>>()
                .Value
                .InputFormatters
                .OfType<NewtonsoftJsonPatchInputFormatter>()
                .First();
        }
    }
    

Der Code oben erstellt eine Instanz von NewtonsoftJsonPatchInputFormatter und fügt sie als ersten Eintrag in der MvcOptions.InputFormatters-Sammlung ein. Durch diese Reihenfolge der Registrierung wird Folgendes sichergestellt:

  • NewtonsoftJsonPatchInputFormatter JSON-Patch-Anfragen verarbeiten
  • Die bestehende System.Text.Json-basierte Eingabe und die Formatierer verarbeiten alle anderen JSON-Anfragen und Antworten.

Verwenden Sie die Newtonsoft.Json.JsonConvert.SerializeObject-Methode zum Serialisieren eines JsonPatchDocument.

PATCH HTTP-Anforderungsmethode

Die Methoden PUT und PATCH werden verwendet, um eine vorhandene Ressource zu aktualisieren. Der Unterschied zwischen den beiden Methoden besteht darin, dass PUT die gesamte Ressource ersetzt, während PATCH nur die Änderungen angibt.

JSON PATCH

JSON Patch ist ein Format zur Spezifikation von Aktualisierungen, die auf eine Ressource angewendet werden sollen. Ein JSON Patch-Dokument verfügt über ein Array von Vorgängen. Jeder Vorgang identifiziert einen bestimmten Änderungstyp. Beispiele für solche Änderungen sind das Hinzufügen eines Arrayelements oder das Ersetzen eines Eigenschaftswerts.

Zum Beispiel repräsentieren die folgenden JSON-Dokumente eine Ressource, ein JSON-Reparaturdokument für die Ressource und das Ergebnis der Anwendung der Reparaturoperationen.

Ressourcenbeispiel

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

JSON Patch-Beispiel

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

Für den oben stehenden JSON-Code gilt:

  • Die op-Eigenschaft gibt den Typ des Vorgangs an.
  • Die path-Eigenschaft gibt das zu aktualisierende Element an.
  • Die value-Eigenschaft stellt den neuen Wert bereit.

Ressource nach dem Patch

So sieht die Ressource nach der Anwendung des voranstehenden JSON Patch-Dokuments aus:

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

Die Änderungen, die durch das Anwenden eines JSON-Patch-Dokuments auf eine Ressource vorgenommen werden, sind unteilbar. Wenn ein Vorgang aus der Liste fehlschlägt, wird kein Vorgang aus der Liste angewendet.

Pfadsyntax

Die path-Eigenschaft eines Vorgangsobjekts weist Schrägstriche zwischen Ebenen auf. Beispiel: "/address/zipCode".

Nullbasierte Indizes werden verwendet, um Arrayelemente anzugeben. Das erste Element des addresses-Arrays wäre bei /addresses/0. Zum add ans Ende eines Arrays verwenden Sie einen Bindestrich (-) anstelle einer Indexnummer: /addresses/-.

Vorgänge

Die folgende Tabelle zeigt unterstützt Vorgänge gemäß der JSON Patch-Spezifikation:

Vorgang Notizen
add Hinzufügen einer Eigenschaft oder eines Arrayelements. Für vorhandene Eigenschaft: set value.
remove Entfernen einer Eigenschaft oder eines Arrayelements.
replace Identisch mit remove, gefolgt von add an gleicher Stelle.
move Identisch mit remove aus der Quelle, gefolgt von add zum Ziel unter Verwendung des Werts aus der Quelle.
copy Identisch mit add zum Ziel unter Verwendung des Werts aus der Quelle.
test Gibt Statuscode für Erfolg zurück, wenn der Wert von path = bereitgestellter value.

JSON-Reparatur in ASP.NET Core

Die ASP.NET Core-Implementierung von JSON Patch wird im Microsoft.AspNetCore.JsonPatch-NuGet-Paket bereitgestellt.

Aktionsmethodencode

Eine Aktionsmethode für JSON Patch in einem API-Controller:

Ein Beispiel:

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

Dieser Code aus der Beispiel-App funktioniert mit dem folgenden Customer-Modell:

namespace JsonPatchSample.Models;

public class Customer
{
    public string? CustomerName { get; set; }
    public List<Order>? Orders { get; set; }
}
namespace JsonPatchSample.Models;

public class Order
{
    public string OrderName { get; set; }
    public string OrderType { get; set; }
}

Die Beispielaktionsmethode:

  • Erstellt ein Objekt vom Typ Customer.
  • Wendet den Patch an.
  • Gibt das Ergebnis wird im Textkörper der Antwort zurück.

In einer realen App würde der Code die Daten aus einem Speicher wie z.B. einer Datenbank abrufen und die Datenbank nach dem Anwenden des Patchs aktualisieren.

Modellstatus

Das voranstehende Aktionsmethodenbeispiel ruft eine Überladung von ApplyTo auf, die den Modellstatus als einen seiner Parameter akzeptiert. Mit dieser Option können Sie Fehlermeldungen in Antworten abrufen. Das folgende Beispiel zeigt den Textkörper einer „400 (Ungültige Anforderung)-Antwort für einen test Vorgang:

{
  "Customer": [
    "The current value 'John' at path 'customerName' != test value 'Nancy'."
  ]
}

Dynamische Objekte

Das folgende Aktionsmethodenbeispiel veranschaulicht das Anwenden ein Patches auf ein dynamisches Objekt:

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

    return Ok(obj);
}

Add-Vorgang (Hinzufügen)

  • Wenn path auf ein Arrayelement verweist: Fügt ein neues Element vor dem von path angegebenen Element ein.
  • Wenn path auf eine Eigenschaft verweist: Legt den Eigenschaftswert fest.
  • Wenn path auf einen nicht vorhandenen Speicherort verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein dynamisches Objekt ist: Fügt eine Eigenschaft hinzu.
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist: Die Anforderung schlägt fehl.

Das folgende Patch-Dokumentbeispiel legt den Wert von CustomerName fest und fügt ein Order-Objekt am Ende des Orders-Arrays hinzu.

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

Remove-Vorgang (Entfernen)

  • Wenn path auf ein Arrayelement verweist: Entfernt das Element.
  • Wenn path auf eine Eigenschaft verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein dynamisches Objekt ist: Entfernt die Eigenschaft.
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist:
      • Wenn die Eigenschaft NULL-Werte zulässt: auf Null festlegen.
      • Wenn die Eigenschaft keine NULL-Werte zulässt: auf default<T> festlegen.

Im folgenden Beispiel legt das Patch-Dokument CustomerName auf Null fest und löscht Orders[0]:

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

Replace-Vorgang (Ersetzen)

Dieser Vorgang ist funktionell identisch mit einem remove, gefolgt von einem add.

Das folgende Patch-Dokumentbeispiel legt den Wert von CustomerName fest und ersetzt Orders[0] durch ein neues Order-Objekt:

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

Move-Vorgang (Verschieben)

  • Wenn path auf ein Arrayelement verweist: Kopiert das from-Element an den Speicherort des path-Elements und führt dann einen remove-Vorgang für das from-Element aus.
  • Wenn path auf eine Eigenschaft verweist: Kopiert den Wert der from-Eigenschaft in die path-Eigenschaft, und führt dann einen remove-Vorgang für die from-Eigenschaft aus.
  • Wenn path auf eine nicht vorhandene Eigenschaft verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist: Die Anforderung schlägt fehl.
    • Wenn es sich bei der Ressource, die gepatcht werden soll, um ein dynamisches Objekt handelt: Kopiert die from-Eigenschaft in den von path angegebenen Speicherort, und führt dann einen remove-Vorgang für die from-Eigenschaft aus.

Das folgende Patch-Dokumentbeispiel:

  • Kopiert den Wert der Orders[0].OrderName nach CustomerName.
  • Legt Orders[0].OrderName auf Null fest.
  • Verschiebt Orders[1] vor Orders[0].
[
  {
    "op": "move",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "move",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Copy-Vorgang (Kopieren)

Dieser Vorgang ist funktionell identisch mit einem move-Vorgang ohne den abschließenden remove-Schritt.

Das folgende Patch-Dokumentbeispiel:

  • Kopiert den Wert der Orders[0].OrderName nach CustomerName.
  • Fügt eine Kopie von Orders[1] vor Orders[0] ein.
[
  {
    "op": "copy",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "copy",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Test-Vorgang (Testen)

Wenn der Wert an dem von path angegebenen Speicherort sich von dem in value bereitgestellten Wert unterscheidet, schlägt die Anforderung fehl. In diesem Fall schlägt die gesamte PATCH-Anforderung fehl, selbst wenn alle anderen Vorgänge im Patch-Dokument ansonsten erfolgreich ausgeführt werden könnten.

Der test-Vorgang wird häufig verwendet, um ein Update zu verhindern, wenn ein Parallelitätskonflikt vorhanden ist.

Das folgende Patch-Dokumentbeispiel hat keine Auswirkungen, wenn der Anfangswert von CustomerName „John“ ist, da der Test fehlschlägt:

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

Abrufen des Codes

Ansicht oder herunterladen von Beispielcode. (Informationen zum Herunterladen)

Um das Beispiel zu testen, führen Sie die App aus, und senden Sie HTTP-Anforderungen mit den folgenden Einstellungen:

  • URL: http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
  • HTTP-Methode: PATCH
  • Header: Content-Type: application/json-patch+json
  • Text Kopieren und einfügen Sie eine der JSON-Reparaturdokument-Stichproben aus dem JSON-Projektordner.

Risikominderung bei der IT-Sicherheit

Bei verwendung des Microsoft.AspNetCore.JsonPatch Pakets mit der Newtonsoft.Json-basierten Implementierung ist es wichtig, potenzielle Sicherheitsrisiken zu verstehen und zu mindern. In den folgenden Abschnitten werden die identifizierten Sicherheitsrisiken im Zusammenhang mit JSON-Patch beschrieben und empfohlene Gegenmaßnahmen bereitgestellt, um die sichere Verwendung des Pakets sicherzustellen.

Von Bedeutung

Dies ist keine vollständige Liste der Bedrohungen. App-Entwickler müssen ihre eigenen Bedrohungsmodellüberprüfungen durchführen, um eine appspezifische umfassende Liste zu ermitteln und bei Bedarf geeignete Gegenmaßnahmen zu erstellen. Beispielsweise sollten Apps, die Sammlungen Patchvorgängen zur Verfügung stellen, das Potenzial für algorithmische Komplexitätsangriffe berücksichtigen, wenn diese Vorgänge Elemente am Anfang der Sammlung einfügen oder entfernen.

Wenn Sie umfassende Bedrohungsmodelle für ihre eigenen Apps ausführen und identifizierte Bedrohungen adressieren und dabei die unten empfohlenen Gegenmaßnahmen befolgen, können Verbraucher dieser Pakete JSON-Patchfunktionen in ihre Apps integrieren und gleichzeitig Sicherheitsrisiken minimieren.

Denial of Service (DoS) über Speicherverstärkung

  • Szenario: Ein böswilliger Client sendet einen copy Vorgang, der große Objektdiagramme mehrmals dupliziert, was zu übermäßigem Arbeitsspeicherverbrauch führt.
  • Wirkung: Potenzielle nicht genügend Arbeitsspeicher-Bedingungen, die Dienstunterbrechungen verursachen.
  • Risikominderung:
    • Überprüfen Sie eingehende JSON Patch-Dokumente auf Größe und Struktur vor dem Aufrufen ApplyTo.
    • Die Überprüfung muss appspezifisch sein, aber eine Beispielüberprüfung kann ähnlich wie folgt aussehen:
public void Validate(JsonPatchDocument patch)
{
    // This is just an example. It's up to the developer to make sure that
    // this case is handled properly, based on the app needs.
    if (patch.Operations.Where(op => op.OperationType == OperationType.Copy).Count()
                              > MaxCopyOperationsCount)
    {
        throw new InvalidOperationException();
    }
}

Geschäftslogik-Subversion

  • Szenario: Patchvorgänge können Felder mit impliziten Invarianten (z. B. interne Flags, IDs oder berechnete Felder) bearbeiten, um Geschäftseinschränkungen zu verletzen.
  • Auswirkung: Datenintegritätsprobleme und unbeabsichtigtes App-Verhalten.
  • Risikominderung:
    • Verwenden Sie POCO-Objekte mit explizit definierten Eigenschaften, die sicher geändert werden können.
    • Vermeiden Sie das Verfügbarmachen vertraulicher oder sicherheitskritischer Eigenschaften im Zielobjekt.
    • Wenn kein POCO-Objekt verwendet wird, überprüfen Sie das gepatchte Objekt nach dem Anwenden von Vorgängen, um sicherzustellen, dass Geschäftsregeln und Invarianten nicht verletzt werden.

Authentifizierung und Autorisierung

  • Szenario: Nicht authentifizierte oder nicht autorisierte Clients senden bösartige JSON-Patchanforderungen.
  • Auswirkung: Nicht autorisierter Zugriff, um vertrauliche Daten zu ändern oder das App-Verhalten zu stören.
  • Risikominderung:
    • Schützen Sie Endpunkte, die JSON-Patchanforderungen mit ordnungsgemäßen Authentifizierungs- und Autorisierungsmechanismen akzeptieren.
    • Einschränken des Zugriffs auf vertrauenswürdige Clients oder Benutzer mit entsprechenden Berechtigungen.

Zusätzliche Ressourcen

In diesem Artikel wird erläutert, wie JSON Patch-Anforderungen in einer ASP.NET Core-Web-API behandelt werden.

Von Bedeutung

Der JSON Patch-Standard hat inhärente Sicherheitsrisiken. Da diese Risiken dem JSON Patch-Standard inhärent sind, versucht diese Implementierung nicht, inhärente Sicherheitsrisiken zu mindern. Es liegt in der Verantwortung des Entwicklers, sicherzustellen, dass das JSON-Patchdokument sicher auf das Zielobjekt angewendet werden kann. Weitere Informationen finden Sie im Abschnitt "Minderung von Sicherheitsrisiken" .

Paketinstallation

Um JSON-Patch-Support in Ihrer App zu aktivieren, folgen Sie diesen Schritten:

  1. Installieren Sie das Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet-Paket.

  2. Aktualisieren Sie die Startup.ConfigureServices-Methode des Projekts so, dass diese AddNewtonsoftJson aufruft. Zum Beispiel:

    services
        .AddControllersWithViews()
        .AddNewtonsoftJson();
    

AddNewtonsoftJson ist kompatibel mit den MVC-Dienstregistrierungsmethoden:

JSON-Reparatur, Hinzufügen von NewtonsoftJson und System.Text.Json

AddNewtonsoftJson ersetzt die auf System.Text.Json basierenden Eingabe/Ausgabe-Formatierer, die zur Formatierung von alle JSON-Inhalte verwendet werden. Um Support für JSON Patch mit „Newtonsoft.Json“ hinzuzufügen, während die anderen Formatierer unverändert bleiben, aktualisieren Sie die Projekt-Startup.ConfigureServices-Methode wie folgt:

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

Der vorangehende Code erfordert das Paket Microsoft.AspNetCore.Mvc.NewtonsoftJson und die folgenden using-Anweisungen:

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;

Verwenden Sie die Newtonsoft.Json.JsonConvert.SerializeObject-Methode, um ein JsonPatchDocument zu serialisieren.

PATCH HTTP-Anforderungsmethode

Die Methoden PUT und PATCH werden verwendet, um eine vorhandene Ressource zu aktualisieren. Der Unterschied zwischen den beiden Methoden besteht darin, dass PUT die gesamte Ressource ersetzt, während PATCH nur die Änderungen angibt.

JSON PATCH

JSON Patch ist ein Format zur Spezifikation von Aktualisierungen, die auf eine Ressource angewendet werden sollen. Ein JSON Patch-Dokument verfügt über ein Array von Vorgängen. Jeder Vorgang identifiziert einen bestimmten Änderungstyp. Beispiele für solche Änderungen sind das Hinzufügen eines Arrayelements oder das Ersetzen eines Eigenschaftswerts.

Zum Beispiel repräsentieren die folgenden JSON-Dokumente eine Ressource, ein JSON-Reparaturdokument für die Ressource und das Ergebnis der Anwendung der Reparaturoperationen.

Ressourcenbeispiel

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

JSON Patch-Beispiel

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

Für den oben stehenden JSON-Code gilt:

  • Die op-Eigenschaft gibt den Typ des Vorgangs an.
  • Die path-Eigenschaft gibt das zu aktualisierende Element an.
  • Die value-Eigenschaft stellt den neuen Wert bereit.

Ressource nach dem Patch

So sieht die Ressource nach der Anwendung des voranstehenden JSON Patch-Dokuments aus:

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

Die Änderungen, die durch das Anwenden eines JSON-Patch-Dokuments auf eine Ressource vorgenommen werden, sind unteilbar. Wenn ein Vorgang aus der Liste fehlschlägt, wird kein Vorgang aus der Liste angewendet.

Pfadsyntax

Die path-Eigenschaft eines Vorgangsobjekts weist Schrägstriche zwischen Ebenen auf. Beispiel: "/address/zipCode".

Nullbasierte Indizes werden verwendet, um Arrayelemente anzugeben. Das erste Element des addresses-Arrays wäre bei /addresses/0. Zum add ans Ende eines Arrays verwenden Sie einen Bindestrich (-) anstelle einer Indexnummer: /addresses/-.

Vorgänge

Die folgende Tabelle zeigt unterstützt Vorgänge gemäß der JSON Patch-Spezifikation:

Vorgang Notizen
add Hinzufügen einer Eigenschaft oder eines Arrayelements. Für vorhandene Eigenschaft: set value.
remove Entfernen einer Eigenschaft oder eines Arrayelements.
replace Identisch mit remove, gefolgt von add an gleicher Stelle.
move Identisch mit remove aus der Quelle, gefolgt von add zum Ziel unter Verwendung des Werts aus der Quelle.
copy Identisch mit add zum Ziel unter Verwendung des Werts aus der Quelle.
test Gibt Statuscode für Erfolg zurück, wenn der Wert von path = bereitgestellter value.

JSON-Reparatur in ASP.NET Core

Die ASP.NET Core-Implementierung von JSON Patch wird im Microsoft.AspNetCore.JsonPatch-NuGet-Paket bereitgestellt.

Aktionsmethodencode

Eine Aktionsmethode für JSON Patch in einem API-Controller:

  • Ist versehen mit dem HttpPatch-Attribut.
  • Akzeptiert eine JsonPatchDocument<T>-Klasse, in der Regel mit [FromBody].
  • Ruft ApplyTo für das Patch-Dokument auf, um die Änderungen anzuwenden.

Ein Beispiel:

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

Dieser Code aus der Beispiel-App funktioniert mit dem folgenden Customer-Modell:

using System.Collections.Generic;

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

Die Beispielaktionsmethode:

  • Erstellt ein Objekt vom Typ Customer.
  • Wendet den Patch an.
  • Gibt das Ergebnis wird im Textkörper der Antwort zurück.

In einer realen App würde der Code die Daten aus einem Speicher wie z.B. einer Datenbank abrufen und die Datenbank nach dem Anwenden des Patchs aktualisieren.

Modellstatus

Das voranstehende Aktionsmethodenbeispiel ruft eine Überladung von ApplyTo auf, die den Modellstatus als einen seiner Parameter akzeptiert. Mit dieser Option können Sie Fehlermeldungen in Antworten abrufen. Das folgende Beispiel zeigt den Textkörper einer „400 (Ungültige Anforderung)-Antwort für einen test Vorgang:

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

Dynamische Objekte

Das folgende Aktionsmethodenbeispiel veranschaulicht das Anwenden ein Patches auf ein dynamisches Objekt:

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

    return Ok(obj);
}

Add-Vorgang (Hinzufügen)

  • Wenn path auf ein Arrayelement verweist: Fügt ein neues Element vor dem von path angegebenen Element ein.
  • Wenn path auf eine Eigenschaft verweist: Legt den Eigenschaftswert fest.
  • Wenn path auf einen nicht vorhandenen Speicherort verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein dynamisches Objekt ist: Fügt eine Eigenschaft hinzu.
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist: Die Anforderung schlägt fehl.

Das folgende Patch-Dokumentbeispiel legt den Wert von CustomerName fest und fügt ein Order-Objekt am Ende des Orders-Arrays hinzu.

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

Remove-Vorgang (Entfernen)

  • Wenn path auf ein Arrayelement verweist: Entfernt das Element.
  • Wenn path auf eine Eigenschaft verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein dynamisches Objekt ist: Entfernt die Eigenschaft.
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist:
      • Wenn die Eigenschaft NULL-Werte zulässt: auf Null festlegen.
      • Wenn die Eigenschaft keine NULL-Werte zulässt: auf default<T> festlegen.

Im folgenden Beispiel legt das Patch-Dokument CustomerName auf Null fest und löscht Orders[0]:

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

Replace-Vorgang (Ersetzen)

Dieser Vorgang ist funktionell identisch mit einem remove, gefolgt von einem add.

Das folgende Patch-Dokumentbeispiel legt den Wert von CustomerName fest und ersetzt Orders[0] durch ein neues Order-Objekt:

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

Move-Vorgang (Verschieben)

  • Wenn path auf ein Arrayelement verweist: Kopiert das from-Element an den Speicherort des path-Elements und führt dann einen remove-Vorgang für das from-Element aus.
  • Wenn path auf eine Eigenschaft verweist: Kopiert den Wert der from-Eigenschaft in die path-Eigenschaft, und führt dann einen remove-Vorgang für die from-Eigenschaft aus.
  • Wenn path auf eine nicht vorhandene Eigenschaft verweist:
    • Wenn die Ressource, auf die der Patch angewendet werden soll, ein statisches Objekt ist: Die Anforderung schlägt fehl.
    • Wenn es sich bei der Ressource, die gepatcht werden soll, um ein dynamisches Objekt handelt: Kopiert die from-Eigenschaft in den von path angegebenen Speicherort, und führt dann einen remove-Vorgang für die from-Eigenschaft aus.

Das folgende Patch-Dokumentbeispiel:

  • Kopiert den Wert der Orders[0].OrderName nach CustomerName.
  • Legt Orders[0].OrderName auf Null fest.
  • Verschiebt Orders[1] vor Orders[0].
[
  {
    "op": "move",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "move",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Copy-Vorgang (Kopieren)

Dieser Vorgang ist funktionell identisch mit einem move-Vorgang ohne den abschließenden remove-Schritt.

Das folgende Patch-Dokumentbeispiel:

  • Kopiert den Wert der Orders[0].OrderName nach CustomerName.
  • Fügt eine Kopie von Orders[1] vor Orders[0] ein.
[
  {
    "op": "copy",
    "from": "/orders/0/orderName",
    "path": "/customerName"
  },
  {
    "op": "copy",
    "from": "/orders/1",
    "path": "/orders/0"
  }
]

Test-Vorgang (Testen)

Wenn der Wert an dem von path angegebenen Speicherort sich von dem in value bereitgestellten Wert unterscheidet, schlägt die Anforderung fehl. In diesem Fall schlägt die gesamte PATCH-Anforderung fehl, selbst wenn alle anderen Vorgänge im Patch-Dokument ansonsten erfolgreich ausgeführt werden könnten.

Der test-Vorgang wird häufig verwendet, um ein Update zu verhindern, wenn ein Parallelitätskonflikt vorhanden ist.

Das folgende Patch-Dokumentbeispiel hat keine Auswirkungen, wenn der Anfangswert von CustomerName „John“ ist, da der Test fehlschlägt:

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

Abrufen des Codes

Ansicht oder herunterladen von Beispielcode. (Informationen zum Herunterladen)

Um das Beispiel zu testen, führen Sie die App aus, und senden Sie HTTP-Anforderungen mit den folgenden Einstellungen:

  • URL: http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
  • HTTP-Methode: PATCH
  • Header: Content-Type: application/json-patch+json
  • Text Kopieren und einfügen Sie eine der JSON-Reparaturdokument-Stichproben aus dem JSON-Projektordner.