C# JSON上的.NET 5 API仅更新字段(部分更新)

C# JSON上的.NET 5 API仅更新字段(部分更新),c#,.net,api,C#,.net,Api,我正在构建一个.NET5API restful,我面临一些问题 我想知道是否可以只更新我在JSON上发送的字段 e、 g: 邮递员 { "id": 14, "name": "Pillar 1" } 我的模型: public class Pillar { [FromRoute] public int ID { get; set; } public string Name { get; set;

我正在构建一个.NET5API restful,我面临一些问题

我想知道是否可以只更新我在JSON上发送的字段

e、 g:

邮递员

{
    "id": 14,
    "name": "Pillar 1"
}
我的模型:

public class Pillar
  {
    [FromRoute]
    public int ID { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }

    public int IDEvaluationType { get; set; }
    
    [ForeignKey("IDEvaluationType")]
    public EvaluationType EvaluationType { get; set; }

    public ICollection<Competence> Competences { get; set; }
  }
公共类支柱
{
[FromRoute]
公共int ID{get;set;}
公共字符串名称{get;set;}
公共bool IsActive{get;set;}
公共int-IDEvaluationType{get;set;}
[外键(“IDEvaluationType”)]
公共EvaluationType EvaluationType{get;set;}
公共ICollection权限{get;set;}
}
我的遥控器

[HttpPut("{id}")]
        public async Task<IActionResult> PutPillar(int id, Pillar pillar)
        {
            if (id != pillar.ID)
            {
                return BadRequest();
            }

            _context.Entry(pillar).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!PillarExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }
[HttpPut(“{id}”)]
公共异步任务PutPillar(int-id,支柱)
{
如果(id!=支柱id)
{
返回请求();
}
_context.Entry(支柱).State=EntityState.Modified;
尝试
{
wait_context.SaveChangesAsync();
}
catch(DbUpdateConcurrencyException)
{
如果(!PillarExists(id))
{
返回NotFound();
}
其他的
{
投掷;
}
}
返回NoContent();
}
但当VS上的请求和调试(我未发送的所有数据)设置为null或0时:

这就是用空值更新我的数据库,丢失我没有用json发送的数据。 我认为实体正在构建这样的查询:

更新支柱集ID=14,名称='Pillar 123',IsActive=null,IDEvaluationType=null,其中ID=14

但需要的是这样的查询:

更新支柱集名称=‘支柱123’,其中ID=14

有没有办法只更新JSON上发送的字段


谢谢,如果有任何问题,请告诉我。

我本可以发表评论,但我没有足够的特权

是的,这是可能的。例如,只需创建一个DTO(数据传输对象)来只更新某些字段

模型


公共类PillarNameUpdateDTO{
[FromRoute]
公共int ID{get;set;}
公共字符串名称{get;set;}
}
控制器


[HttpPut(“{id}/name”)]
公共异步任务PutPillar(int-id,pillarname更新为dto)
{
if(id!=dto.id)
{
返回请求();
}
//拿柱子
var-pillar=_context.Pillars.Find(dto.ID);
如果(支柱==null){
//抛出错误,
返回NotFound();
}
支柱名称=dto.Name;
_背景。更新(支柱);
_SaveChanges();
返回NoContent();
}

可以只更改某些特定对象的字段子集,该操作称为“修补”。对于REST服务,您必须使用补丁而不是PUT,因为PUT总是意味着整个对象的更改


微软网站上有一篇文章,如何实现PATСH请求处理,请看一看:

实现这一点的唯一方法如下:

修改类或创建viewModel:

public class Pillar
  {
    [FromRoute]
    public int ID { get; set; }
    public string? Name { get; set; }
    public bool? IsActive { get; set; }
    [Required]
    public int? IDEvaluationType { get; set; }
    
    [ForeignKey("IDEvaluationType")]
    public EvaluationType EvaluationType { get; set; }

    public ICollection<Competence> Competences { get; set; }
  }
像这样使用它

  if(pillar.Name!="NotAssigned") existed.Name=pillar.Name;

您需要加载支柱更改字段并进行更新…答案是肯定的,有很多方法可以做到这一点。你需要关注你的问题,并添加更多关于你的技术堆栈的信息。查看JSON补丁。首先,我不相信像这样的查询更新支柱集ID=14,Name='Pillar 123',IsActive=null是真的,因为
IsActive
在模型中不可为null,这会导致另一个问题,如果您发送
{“ID”:14,“Name”:“支柱1”,“IsActive”:false}
,它在您的情况下与
{“ID”:14,“Name”:“支柱1”相同}
默认值为
bool
值为
false
首先,感谢您的支持。好的,我可以创建一个dto来更新名称,但是路由应该允许更新任何字段。示例:如果我发送以下json:{“id”:14,“isActive”:false},代码必须只编辑isActive字段。或者,即使我发送以下内容:{“id”:14,“name”:“支柱13232”,“isActive”:false}。它应该更新名称和isActive字段。有问题就告诉我,伙计
public class Pillar
  {
    [FromRoute]
    public int ID { get; set; }
    public string? Name { get; set; }
    public bool? IsActive { get; set; }
    [Required]
    public int? IDEvaluationType { get; set; }
    
    [ForeignKey("IDEvaluationType")]
    public EvaluationType EvaluationType { get; set; }

    public ICollection<Competence> Competences { get; set; }
  }
 public async Task<IActionResult> PutPillar(int id, Pillar pillar)
        {
            if (id != pillar.ID)
            {
                return BadRequest();
            }
            var existed = _context.Pillars.FirstOrDefault(i=>i.ID=pillar.ID);
            if(pillar.Name!=null) existed.Name=pillar.Name;
            if(pillar.IsActive!=null) existed.IsActive=pillar.IsActive;
            .... and so on

            _context.Entry(existed).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!PillarExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }
public  Pillar()
{
  Name="NotAssigned";
}
  if(pillar.Name!="NotAssigned") existed.Name=pillar.Name;