【问题标题】:How to prevent remove operation in Json Patch Document .NET Core Web API如何防止 Json Patch Document .NET Core Web API 中的删除操作
【发布时间】:2021-07-28 17:47:21
【问题描述】:

我在我的 Web API 项目中使用 .NET core 和 EF。

我想要一个补丁端点来更新一个实体。我发现这篇文章说

删除 与上述“添加”操作类似,删除 操作通常意味着您要从 对象或从数组中删除项目。但是因为你不能 实际上从 C# 中的对象中“删除”一个属性,实际上是什么 发生的是它会将值设置为默认值(T)。在某些情况下,如果 对象可以为空(或引用类型),它将被设置为 NULL。 但要小心,因为当用于值类型时,例如 int, 然后该值实际上被重置为“0”。

我不希望客户发送删除操作,这将重置他的一些字段或使用Add 操作添加新字段

所以在这里我想创建 PATCH 端点来更新人 FirstNameAge 仅使用 replace 操作。

我有一个Person 实体和UpdatePersonDTO,如下所示

public partial class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public int Age { get; set; }
}

public partial class PersonDTO
{
    public string FirstName { get; set; }
    public int Age { get; set; }
}

这是我当前的代码

public async Task<Object> UpdatePerson(int id , JsonPatchDocument<PersonRequestDTO> patchDocument) {

var result = _dbContext.persons
   .Where(P => P.id == id).FirstOrDefault();


var personToPatch = _mapper.Map<PersonRequestDTO>(result);
patchDocument.ApplyTo(personToPatch);
_mapper.Map(personToPatch, result);

// rest of code and returning updated entitiy dto... 
}

现在实现这一目标的方法是什么?为什么我找不到类似的问题? 我认为remove 操作非常关键,所以现在我觉得我实际上在这里遗漏了一些东西。

【问题讨论】:

  • 什么文章?您的代码将具有特定属性的 Person 对象更新到具有特定列的表中。它不能添加或删除字段和列。充其量,它会将属性设置为null0,这与更新对象并将它们显式设置为null 或0 没有什么不同
  • 事实上,您发布的摘录中说属性不能被删除。假设您阅读了this article,它说明无法添加或删除属性。
  • @PanagiotisKanavos 是的,你是对的。唯一的区别是,从我们的前端发送的数据永远不会是 0 或 null,它们总是带有有效数据。我们允许用户从映射到我们数据库的下拉列表中选择数据。模型不是人,但为了简单起见,我选择了人。这是文章dotnetcoretutorials.com/2017/11/29/json-patch-asp-net-core
  • 这与使用 PUT 将它们设置为 0 有何不同?还是replace?如果您不希望这些字段可以为空,请在实体、表列和验证中指定它。 NOT NULL 列不能设置为 NULL[Required] 属性不能为 NULL。顺便说一句,映射器在这里不提供任何东西。你不需要那个PersonDTOdocumentation example 要简单得多 并且 使用验证。使用patchDoc.ApplyTo(customer, ModelState);,您可以检查ModelState.IsValid
  • @Jack 那为什么不问一个关于那个的问题呢?

标签: c# asp.net asp.net-core patch webapi


【解决方案1】:

正如文章所说,AddRemove 不能在 C# 中添加或删除属性,只能添加或删除数组项。 remove 相当于将属性设置为 null,或者如果它是值类型,则设置为默认值。

验证规则和属性可以检测到这一点。 JSON Patch example in the ASP.NET Core docs 正好展示了这种情况。稍作修改:

[HttpPatch]
public IActionResult JsonPatchWithModelState(
    int id,
    [FromBody] JsonPatchDocument<Person> patchDoc)
{
    if (patchDoc != null)
    {
        var person = _dbContext.persons
                         .Find(id)
                         .FirstOrDefault();

        patchDoc.ApplyTo(person, ModelState);

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

        _dbContext.SaveChanges();
        return new ObjectResult(person);

    }
    else
    {
        return BadRequest(ModelState);
    }
}

Person 类添加验证属性将确保它不能接受无效数据:

public partial class Person
{
    public int Id { get; set; }

    [Required]
    public string FirstName { get; set; }

    [Range(1,199)]
    public int Age { get; set; }
}

如果我们担心PATCH 可能会修改ID,并且该字段不是 数据库生成的,我们可以检查person.id 是否未更改:

if (!ModelState.IsValid || person.id!=id)
{
    if (person.id!=id)
    {
        ModelState.AddError("id","Not Editable");
    }
    return BadRequest(ModelState);
}

【讨论】:

  • 检查是否 (person.id!=id) 将始终返回 true,因为您正在使用传递的 id 填充人员对象。
猜你喜欢
  • 2017-08-01
  • 2015-01-19
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 2023-03-15
  • 2021-10-12
相关资源
最近更新 更多