事件
Power BI DataViz World Championships
2月14日 下午4時 - 3月31日 下午4時
4 次參賽機會,有機會贏得會議套裝行程,現場參與在拉斯維加斯舉行的總決賽
進一步了解本文說明如何處理 ASP.NET Core Web API 中的 JSON Patch 要求。
ASP.NET Core Web API 中的 JSON 修補檔支援是以 Newtonsoft.Json
為基礎且需要 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件。 若要啟用 JSON 修補檔支援:
安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件。
呼叫 AddNewtonsoftJson。 例如:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
AddNewtonsoftJson
會取代用於格式化 System.Text.Json
JSON 內容的預設 型輸入和輸出格式器。 此擴充方法與下列 MVC 服務註冊方法相容:
JsonPatch 需要將 Content-Type
標頭設定為 application/json-patch+json
。
System.Text.Json
型輸入格式器不支援 JSON修補檔。 若要使用 Newtonsoft.Json
新增對 JSON 修補檔的支援,同時讓其他輸入和輸出格式器保持不變:
安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件。
更新 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();
}
}
上述程式碼會建立 NewtonsoftJsonPatchInputFormatter 執行個體,並將它插入為 MvcOptions.InputFormatters 集合中的第一個輸入。 此註冊順序可確保:
NewtonsoftJsonPatchInputFormatter
處理 JSON 修補檔要求。System.Text.Json
型輸入和格式器會處理所有其他 JSON 要求與回應。使用 Newtonsoft.Json.JsonConvert.SerializeObject
方法序列化 JsonPatchDocument。
PUT 和 PATCH \(英文\) 方法均用來更新現有的資源。 它們之間的差異是 PUT 會取代整個資源,而 PATCH 只會指定變更。
JSON Patch \(英文\) 是一種格式,可用來指定要套用至資源的更新。 JSON Patch 文件具有一個「作業」陣列。 每個作業都會識別特定類型的變更。 這類變更的範例包括新增陣列元素或取代屬性值。
例如,下列 JSON 文件代表一個資源、一份適用於該資源的 JSON 修補文件,以及套用修補作業的結果。
{
"customerName": "John",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
}
]
}
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
在上述 JSON 中:
op
屬性會指出作業的類型。path
屬性會指出要更新的元素。value
屬性會提供新值。以下是套用上述 JSON Patch 文件之後的資源:
{
"customerName": "Barry",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
},
{
"orderName": "Order2",
"orderType": null
}
]
}
將 JSON 修補文件套用至資源所做的變更是不可部分完成的。 如果清單中有任何作業失敗,則不會套用清單中的任何作業。
作業物件的 path \(英文\) 屬性在層級之間有斜線。 例如: "/address/zipCode"
。
以零為起始的索引可用來指定陣列元素。
addresses
陣列的第一個元素會在 /addresses/0
上。 若要將 add
到陣列結尾處,請使用連字號 (-
) 而不是索引號碼:/addresses/-
。
下表顯示支援的作業,如 JSON Patch 規格 \(英文\) 中所定義:
作業 | 備註 |
---|---|
add |
加入屬性或陣列元素。 針對現有的屬性:設定值。 |
remove |
移除屬性或陣列元素。 |
replace |
與 remove 之後接著在同一個位置上 add 相同。 |
move |
與從來源 remove 之後接著使用來源的值 add 到目的地相同。 |
copy |
與使用來源的值 add 到目的地相同。 |
test |
如果 path 上的值 = 所提供的 value ,即會傳回成功狀態碼。 |
Microsoft.AspNetCore.JsonPatch \(英文\) NuGet 套件中會提供 JSON Patch 的 ASP.NET Core 實作。
在 API 控制器中,JSON Patch 的動作方法:
HttpPatch
屬性來標註。[FromBody]
。以下為範例:
[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);
}
}
這段來自範例應用程式的程式碼會使用下列 Customer
模型:
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; }
}
範例動作方法:
Customer
。在實際的應用程式中,程式碼會從資料庫之類的存放區擷取資料,並在套用修補檔案之後更新資料庫。
上述動作方法範例會呼叫 ApplyTo
的多載,以取得模型狀態作為它的其中一個參數。 使用此選項,您就能在回應中收到錯誤訊息。 下列範例會針對 test
作業顯示「400 不正確的要求」回應的本文:
{
"Customer": [
"The current value 'John' at path 'customerName' != test value 'Nancy'."
]
}
下列動作方法範例示範如何將修補檔套用至動態物件:
[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
dynamic obj = new ExpandoObject();
patch.ApplyTo(obj);
return Ok(obj);
}
path
指向陣列元素:將新元素插入至 path
所指定的元素之前。path
指向屬性:設定屬性值。path
指向不存在的位置:下列範例修補文件會設定 CustomerName
的值,並將 Order
物件加入至 Orders
陣列的結尾處。
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
path
指向陣列元素:移除該元素。path
指向屬性:default<T>
。下列範例修補文件會將 CustomerName
設定為 Null 並刪除 Orders[0]
:
[
{
"op": "remove",
"path": "/customerName"
},
{
"op": "remove",
"path": "/orders/0"
}
]
此作業在功能上與 remove
之後接著 add
相同。
下列範例修補文件會設定 CustomerName
的值,並使用新的 Orders[0]
物件來取代 Order
:
[
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
path
指向陣列元素:將 from
元素複製到 path
元素的位置,然後在 remove
元素上執行 from
作業。path
指向屬性:將 from
屬性的值複製到 path
屬性,然後在 remove
屬性上執行 from
作業。path
指向不存在的屬性:from
屬性複製到 path
所指出的位置,然後在 remove
屬性上執行 from
作業。下列範例修補文件:
Orders[0].OrderName
的值複製到 CustomerName
。Orders[0].OrderName
設定為 Null。Orders[1]
移到 Orders[0]
前面。[
{
"op": "move",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "move",
"from": "/orders/1",
"path": "/orders/0"
}
]
此作業在功能上與不含最後 move
步驟的 remove
作業相同。
下列範例修補文件:
Orders[0].OrderName
的值複製到 CustomerName
。Orders[1]
前面插入 Orders[0]
的複本。[
{
"op": "copy",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "copy",
"from": "/orders/1",
"path": "/orders/0"
}
]
如果 path
所指出位置上的值與 value
中所提供的值不同,則要求會失敗。 在該情況下,整個 PATCH 要求會失敗,即使修補文件中的所有其他作業都成功也一樣。
test
作業通常會用來防止在發生並行衝突時進行更新。
如果 CustomerName
的初始值是 "John",則下列範例修補文件不會有任何作用,因為測試失敗:
[
{
"op": "test",
"path": "/customerName",
"value": "Nancy"
},
{
"op": "add",
"path": "/customerName",
"value": "Barry"
}
]
檢視或下載範例程式碼。 (如何下載)。
若要測試範例,請執行應用程式,並使用下列設定來傳送 HTTP 要求:
http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
PATCH
Content-Type: application/json-patch+json
本文說明如何處理 ASP.NET Core Web API 中的 JSON Patch 要求。
若要在您的應用程式中啟用 JSON 修補檔支援,請完成下列步驟:
安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 套件。
更新專案的 Startup.ConfigureServices
方法以呼叫 AddNewtonsoftJson。 例如:
services
.AddControllersWithViews()
.AddNewtonsoftJson();
AddNewtonsoftJson
與 MVC 服務註冊方法相容:
AddNewtonsoftJson
會取代用於格式化 System.Text.Json
JSON 內容的 型輸入和輸出格式器。 若要使用 Newtonsoft.Json
新增對 JSON 修補檔的支援,同時讓其他格式器保持不變,請更新專案的 Startup.ConfigureServices
方法,如下所示:
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();
}
上述程式碼需要 Microsoft.AspNetCore.Mvc.NewtonsoftJson
套件和下列 using
陳述式:
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.SerializeObject
方法來序列化 JsonPatchDocument。
PUT 和 PATCH \(英文\) 方法均用來更新現有的資源。 它們之間的差異是 PUT 會取代整個資源,而 PATCH 只會指定變更。
JSON Patch \(英文\) 是一種格式,可用來指定要套用至資源的更新。 JSON Patch 文件具有一個「作業」陣列。 每個作業都會識別特定類型的變更。 這類變更的範例包括新增陣列元素或取代屬性值。
例如,下列 JSON 文件代表一個資源、一份適用於該資源的 JSON 修補文件,以及套用修補作業的結果。
{
"customerName": "John",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
}
]
}
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
在上述 JSON 中:
op
屬性會指出作業的類型。path
屬性會指出要更新的元素。value
屬性會提供新值。以下是套用上述 JSON Patch 文件之後的資源:
{
"customerName": "Barry",
"orders": [
{
"orderName": "Order0",
"orderType": null
},
{
"orderName": "Order1",
"orderType": null
},
{
"orderName": "Order2",
"orderType": null
}
]
}
將 JSON 修補文件套用至資源所做的變更是不可部分完成的。 如果清單中有任何作業失敗,則不會套用清單中的任何作業。
作業物件的 path \(英文\) 屬性在層級之間有斜線。 例如: "/address/zipCode"
。
以零為起始的索引可用來指定陣列元素。
addresses
陣列的第一個元素會在 /addresses/0
上。 若要將 add
到陣列結尾處,請使用連字號 (-
) 而不是索引號碼:/addresses/-
。
下表顯示支援的作業,如 JSON Patch 規格 \(英文\) 中所定義:
作業 | 備註 |
---|---|
add |
加入屬性或陣列元素。 針對現有的屬性:設定值。 |
remove |
移除屬性或陣列元素。 |
replace |
與 remove 之後接著在同一個位置上 add 相同。 |
move |
與從來源 remove 之後接著使用來源的值 add 到目的地相同。 |
copy |
與使用來源的值 add 到目的地相同。 |
test |
如果 path 上的值 = 所提供的 value ,即會傳回成功狀態碼。 |
Microsoft.AspNetCore.JsonPatch \(英文\) NuGet 套件中會提供 JSON Patch 的 ASP.NET Core 實作。
在 API 控制器中,JSON Patch 的動作方法:
HttpPatch
屬性來標註。JsonPatchDocument<T>
來接受 [FromBody]
。ApplyTo
以套用變更。以下為範例:
[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);
}
}
這段來自範例應用程式的程式碼會使用下列 Customer
模型:
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; }
}
}
範例動作方法:
Customer
。在實際的應用程式中,程式碼會從資料庫之類的存放區擷取資料,並在套用修補檔案之後更新資料庫。
上述動作方法範例會呼叫 ApplyTo
的多載,以取得模型狀態作為它的其中一個參數。 使用此選項,您就能在回應中收到錯誤訊息。 下列範例會針對 test
作業顯示「400 不正確的要求」回應的本文:
{
"Customer": [
"The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
]
}
下列動作方法範例示範如何將修補檔套用至動態物件:
[HttpPatch]
public IActionResult JsonPatchForDynamic([FromBody]JsonPatchDocument patch)
{
dynamic obj = new ExpandoObject();
patch.ApplyTo(obj);
return Ok(obj);
}
path
指向陣列元素:將新元素插入至 path
所指定的元素之前。path
指向屬性:設定屬性值。path
指向不存在的位置:下列範例修補文件會設定 CustomerName
的值,並將 Order
物件加入至 Orders
陣列的結尾處。
[
{
"op": "add",
"path": "/customerName",
"value": "Barry"
},
{
"op": "add",
"path": "/orders/-",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
path
指向陣列元素:移除該元素。path
指向屬性:default<T>
。下列範例修補文件會將 CustomerName
設定為 Null 並刪除 Orders[0]
:
[
{
"op": "remove",
"path": "/customerName"
},
{
"op": "remove",
"path": "/orders/0"
}
]
此作業在功能上與 remove
之後接著 add
相同。
下列範例修補文件會設定 CustomerName
的值,並使用新的 Orders[0]
物件來取代 Order
:
[
{
"op": "replace",
"path": "/customerName",
"value": "Barry"
},
{
"op": "replace",
"path": "/orders/0",
"value": {
"orderName": "Order2",
"orderType": null
}
}
]
path
指向陣列元素:將 from
元素複製到 path
元素的位置,然後在 remove
元素上執行 from
作業。path
指向屬性:將 from
屬性的值複製到 path
屬性,然後在 remove
屬性上執行 from
作業。path
指向不存在的屬性:from
屬性複製到 path
所指出的位置,然後在 remove
屬性上執行 from
作業。下列範例修補文件:
Orders[0].OrderName
的值複製到 CustomerName
。Orders[0].OrderName
設定為 Null。Orders[1]
移到 Orders[0]
前面。[
{
"op": "move",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "move",
"from": "/orders/1",
"path": "/orders/0"
}
]
此作業在功能上與不含最後 move
步驟的 remove
作業相同。
下列範例修補文件:
Orders[0].OrderName
的值複製到 CustomerName
。Orders[1]
前面插入 Orders[0]
的複本。[
{
"op": "copy",
"from": "/orders/0/orderName",
"path": "/customerName"
},
{
"op": "copy",
"from": "/orders/1",
"path": "/orders/0"
}
]
如果 path
所指出位置上的值與 value
中所提供的值不同,則要求會失敗。 在該情況下,整個 PATCH 要求會失敗,即使修補文件中的所有其他作業都成功也一樣。
test
作業通常會用來防止在發生並行衝突時進行更新。
如果 CustomerName
的初始值是 "John",則下列範例修補文件不會有任何作用,因為測試失敗:
[
{
"op": "test",
"path": "/customerName",
"value": "Nancy"
},
{
"op": "add",
"path": "/customerName",
"value": "Barry"
}
]
檢視或下載範例程式碼。 (如何下載)。
若要測試範例,請執行應用程式,並使用下列設定來傳送 HTTP 要求:
http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate
PATCH
Content-Type: application/json-patch+json
事件
Power BI DataViz World Championships
2月14日 下午4時 - 3月31日 下午4時
4 次參賽機會,有機會贏得會議套裝行程,現場參與在拉斯維加斯舉行的總決賽
進一步了解訓練
模組
Perform custom updates in a Power Apps canvas app - Training
With some Power Apps canvas apps, a form isn't the solution. This module focuses on how to perform custom updates when your data isn't in a form.