C# asp web api修补程序的实现

C# asp web api修补程序的实现,c#,asp.net,rest,model,asp.net-web-api,C#,Asp.net,Rest,Model,Asp.net Web Api,假设我有这个模型 public partial class Todo { public int id { get; set; } public string content { get; set; } public bool done { get; set; } } 我将它作为json数据作为补丁请求发送给我的控制器。 这只是切换复选框的操作。 我认为我只想把它发送到我的服务器,而不是整个模型 { "id":1, "done" : true } 为了正确处理这个简单的

假设我有这个模型

public partial class Todo
{
    public int id { get; set; }
    public string content { get; set; }
    public bool done { get; set; }
}
我将它作为json数据作为补丁请求发送给我的控制器。 这只是切换复选框的操作。 我认为我只想把它发送到我的服务器,而不是整个模型

{ "id":1, "done" : true }
为了正确处理这个简单的json补丁请求,我的WebApi控制器需要什么样的外观?我应该为此使用WebAPI,还是应该在mvc中使用更具rpc风格的方法

这似乎是一件非常基本的事情,但我似乎做不好! 我想我可能需要在控制器方法中使用不同的参数,但我不确定


谢谢您的时间。

ASP.NET Web API似乎缺少
UpdateModel
TryUpdateModel
,等等


在ASP.NET MVC中,您可以使用它们来实现所需的效果。我已经在ASP.NET中创建了一个Web堆栈,您可以投票支持它,如果它获得足够的票数,它将被实现。

将方法更改为补丁不会以任何方式改变Web API行为。没有用于执行部分更新的内置机制。长久以来没有补丁方法的原因之一是,没有无处不在的媒体类型可用于将补丁应用于资源

第二,您要求WebAPI为您执行对象序列化,因此没有应用部分更新对象的概念。会有很多约定需要达成一致,空值意味着什么,空值意味着什么,我怎么说“不要更新这个日期时间”。那么相关对象、子项呢?如何使子项被删除?除非CLR团队实现了某个类型的概念,该类型只包含来自另一个类型的成员子集,否则部分更新和对象序列化不会很好地结合在一起

Aliostad提到UpdateModel,这在从HTML表单更新时是可能的,因为媒体类型
application/x-www-form-urlencoded
明确允许一组任意的名称-值对。没有正在进行的“对象序列化”。它只是将表单中的名称与模型对象上的名称进行匹配


就我自己而言,我创建了一种新的媒体类型,用于执行类似表单的部分更新,但更高级的是,它可以处理层次结构数据,并维护更新顺序。

您可以在OData预发布Nuget包中找到补丁功能:

关于如何使用它创建处理补丁的操作的信息,可以在博客文章的部分更新(补丁请求)部分找到。

我用于我的项目,在使用JSON时遇到一些问题(在我的案例中使用数字)。另外,在我看来,OData包有一些依赖项,它们对于单个功能来说太大了(所有依赖项都是7MB)

所以我开发了一个简单的库,可以满足您的要求:

如何使用

使用以下方法安装软件包:

Install-Package SimplePatch
然后在控制器中:

[HttpPatch]
public IHttpActionResult PatchOne(Delta<Todo> todo)
{
    if (todo.TryGetPropertyValue(nameof(Todo.id), out int id)) {
        // Entity to update (from your datasource)
        var todoToPatch = Todos.FirstOrDefault(x => x.id == id);
        if (todoToPatch == null) return BadRequest("Todo not found");

        todo.Patch(todoToPatch);     

        // Now todoToPatch is updated with new values            
    } else {
        return BadRequest();
    }     

    return Ok();
}
此外,在调用
Patch
方法时,可以排除一些要更新的属性。 Global.asax或Startup.cs

DeltaConfig.Init((cfg) =>
{
    cfg.ExcludeProperties<Todo>(x => x.id);
});
DeltaConfig.Init((cfg)=>
{
ExcludeProperties(x=>x.id);
});

当您使用实体而不想创建模型时,此选项非常有用。

+1。您的媒体类型格式化程序是否可以包含在web api contrib中?这是一个常见的场景,我可以想象这样的功能经常被请求。感谢您的回答,如果我只想更新模型的一个字段(此场景中的“完成”复选框字段),正确的方法是什么?我应该放弃web api吗?如何在不丢失模型验证的情况下执行此操作?很难相信asp.net中的“最新者中的最新者”不可能实现如此简单的操作technologies@Aliostad我正在为我的EventSequence媒体类型发布规范和解析器。它将与Web Api配合使用。关于更多信息,我在RESTFest上做了一个快速的屏幕广播,这里看一下这个示例,它通过json.net序列化程序进行修补,而不依赖于oData wire格式-您可以使用JsonPatch,它受ASP.net、ASP.net Core和PCL For Xamarin的支持。好文章可以在这里找到,这是一个不同的问题,我认为。我的模型不是基于json的。实际的状态更新将如何进行应该取决于实现者。我不想把一些RFC规范转换成SQL查询或实体。
entity.Patch(entityToPatch);

dbContext.Entry(entityToPatch).State = EntityState.Modified;
dbContext.SaveChanges();
DeltaConfig.Init((cfg) =>
{
    cfg.ExcludeProperties<Todo>(x => x.id);
});