我正在尝试在ASP.NET Core中使用JsonPatch来处理模型的部分更新,但在将PATCH发送到Web API控制器操作时遇到绑定问题:
我正在使用一个小型库来发出PATCH请求:
axios
.patch('http://localhost:8090/api/characters/1', { bookId: 1, name: 'Bob'})
.then(function () { /*...*/ })
.catch(function() { /*...*/ });
这是原始请求:
PATCH http://localhost:8090/api/characters/6 HTTP/1.1
Host: localhost:8090
Connection: keep-alive
Content-Length: 30
Accept: application/json, text/plain, */*
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:3000/library/book/2/character/6
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-AU,en;q=0.8,ru;q=0.6
{"bookId":1,"name":"Bob"}
我的ViewModel:
public class UpdateCharacterViewModel
{
public string Name { get; set; }
}
最后,Web API操作:
[Route("~/api/[controller]/{characterId}")]
[HttpPatch]
public IActionResult Update(int characterId, [FromBody]UpdateCharacterViewModel viewModel, [FromBody]JsonPatchDocument<UpdateCharacterViewModel> patch)
{
// viewModel is bound correctly but patch is NULL
// ...
}
我发现patch
以NULL
的形式出现,表明绑定存在问题。要检查请求是否存在问题,我添加了viewModel
并发现它正确绑定 - 操作可以使用已填充的UpdateCharacterViewModel
。
我在这里做错了什么?
答案 0 :(得分:5)
以下是使用JsonPatchDocument正常工作的请求的示例:
PATCH /api/characters/1
[
{
"op": "replace",
"path": "/name",
"value": "Bob"
}
]
值得庆幸的是,有一些库可以轻松创建这个补丁数据。 JSON-patch似乎很好。您可以通过观察对象的更改来生成补丁数据:
var myobj = { firstName:"Joachim", lastName:"Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } };
observer = jsonpatch.observe( myobj );
myobj.firstName = "Albert";
myobj.contactDetails.phoneNumbers[0].number = "123";
myobj.contactDetails.phoneNumbers.push({number:"456"});
var patches = jsonpatch.generate(observer);
// patches == [
// { op:"replace", path="/firstName", value:"Albert"},
// { op:"replace", path="/contactDetails/phoneNumbers/0/number", value:"123"},
// { op:"add", path="/contactDetails/phoneNumbers/1", value:{number:"456"}}];
或者可选地,您可以在两个对象之间运行差异:
var objA = {user: {firstName: "Albert", lastName: "Einstein"}};
var objB = {user: {firstName: "Albert", lastName: "Collins"}};
var diff = jsonpatch.compare(objA, objB));
//diff == [{op: "replace", path: "/user/lastName", value: "Collins"}]
最后,要小心我调试API控制器操作的尝试。根据{{3}}的答案,您只能使用[FromBody]
属性修饰一个参数。所有后续参数可能不受约束!