9

问题是什么?

我正在尝试在我的 ASP.net Web api 应用程序中启用补丁。我正在使用代码优先实体框架。

我有以下方法头,我可以在其中设置断点,它会命中:

[AcceptVerbs("PATCH")]
public async Task<HttpResponseMessage> Patch(long appId, long id, Delta<SimpleFormGroup> formGroup)

但是,当我调用 formGroup.Patch(entity) 时,不会对我的实体进行任何更改。如果我将以下内容放入即时窗口:

formGroup.GetChangedPropertyNames()

那么这个集合是空的,这似乎是错误的。

我尝试了什么?

我一直在参考以下示例

http://techbrij.com/http-patch-request-asp-net-webapi http://www.strathweb.com/2013/01/easy-asp-net-web-api-resource-updates-with-delta /

Json MediaType Formatter 不知道如何正确构建 Delta 对象似乎是一个问题,但是在第二个链接中 filip 似乎确实表明它应该在没有 oDataMediaTypeFormatter 的情况下工作。

我已经开始尝试将我的模型序列化为 EDMX 表示,然后从那里提取 CSDL,以便我可以创建一个 oDataMediaTypeFormatter,但我也遇到了障碍,而且这似乎有点矫枉过正。

如果有人能对此有所了解,将不胜感激。让我知道是否需要更多信息。

编辑:

这是 SimpleFormGroup 的类定义:

public class SimpleFormGroup
{
    public int LastUpdate;

    public string Identifier;

    public string Title;

    public int DisplayOrder;
}

这是我要发送的数据:

Content-Type: 'application/json'

{ "DisplayOrder" : "20 }
4

2 回答 2

9

Interesting, it looks like Delta<T> with int members doesn't work in JSON.

Unfortunately, Delta<T> was created specifically for OData. If Delta<T> appears to be working with any formatter other than OData, it's a coincidence rather than being intentional.

The good news though is that there's nothing stopping you from defining your own PATCH format for JSON, and I'd be surprised if no one has already written one that works better with Json.NET. It's possible that we'll revisit patching in a future release of Web API and try to come up with a consistent story that works across formatters.

于 2013-02-06T16:42:42.233 回答
4

感谢 Youssef 调查并发现了为什么事情不起作用。希望这可以得到解决。

在仔细研究了 oData 包源之后,我最终自己破解了这个问题。我选择实现另一个包含逻辑的 MediaTypeFormatter,因为它提供了轻松访问 tio HttpContent,但还有其他方法可以实现这一点。

关键部分是弄清楚如何解释代码优先模型,请参见下面的注释行:

public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
    var builder = new ODataConventionModelBuilder();

    // This line will allow you to interpret all the metadata from your code first model
    builder.EntitySet<EfContext>("EfContext");

    var model = builder.GetEdmModel();
    var odataFormatters = ODataMediaTypeFormatters.Create(model);
    var delta = content.ReadAsAsync(type, odataFormatters).Result; 

    var tcs = new TaskCompletionSource<object>(); 
    tcs.SetResult(delta); 
    return tcs.Task; 
}

希望这可以为某人节省一些麻烦!

于 2013-02-08T09:12:26.953 回答