简体   繁体   English

如何使用Microsoft ASP.NET Web API OData中的Delta <T>和Code First \ JsonMediaTypeFormatter

[英]How to use Delta<T> from Microsoft ASP.NET Web API OData with Code First\JsonMediaTypeFormatter

What is the issue? 有什么问题?

I am trying to enable patching in my ASP.net web api app. 我正在尝试在我的ASP.net web api应用程序中启用修补程序。 I'm using code first entity framework. 我正在使用代码第一实体框架。

I have the following method header which I can set a breakpoint in and it will hit: 我有以下方法标题,我可以设置一个断点,它将命中:

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

However when I call formGroup.Patch(entity), no changes are made to my entity. 但是,当我调用formGroup.Patch(实体)时,不会对我的实体进行任何更改。 If I put the following into the immediate window: 如果我将以下内容放入即时窗口:

formGroup.GetChangedPropertyNames()

Then this collection is empty, which seems wrong. 然后这个集合是空的,这似乎是错误的。

What have I tried? 我试过了什么?

I have been referring to the following examples 我一直在提到以下例子

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

It seems to be a problem with the Json MediaType Formatter not knowing how to build the Delta object correctly, however in the 2nd link filip does seem to suggest that it should work without the oDataMediaTypeFormatter. Json MediaType Formatter似乎不知道如何正确构建Delta对象,但是在第二个链接中,filip似乎表明它应该在没有oDataMediaTypeFormatter的情况下工作。

I have started down the line of trying to serialise my model to EDMX representation, then from there extract the CSDL so I can create an oDataMediaTypeFormatter, but I have hit a snag there too, plus it seems a bit overkill. 我已经开始试图将我的模型序列化为EDMX表示,然后从那里提取CSDL以便我可以创建一个oDataMediaTypeFormatter,但我也遇到了障碍,加上它似乎有点矫枉过正。

If anyone could shed any light on this it'd be much appreciated. 如果有人能够对此有所了解,那将非常感激。 Let me know if any more information is needed. 如果需要更多信息,请与我们联系。

EDIT: 编辑:

Here is the class definition for SimpleFormGroup: 这是SimpleFormGroup的类定义:

public class SimpleFormGroup
{
    public int LastUpdate;

    public string Identifier;

    public string Title;

    public int DisplayOrder;
}

And here is the data that I am sending: 这是我发送的数据:

Content-Type: 'application/json'

{ "DisplayOrder" : "20 }

Interesting, it looks like Delta<T> with int members doesn't work in JSON. 有趣的是,看起来像Delta<T>的int成员在JSON中不起作用。

Unfortunately, Delta<T> was created specifically for OData. 不幸的是, Delta<T>是专门为OData创建的。 If Delta<T> appears to be working with any formatter other than OData, it's a coincidence rather than being intentional. 如果Delta<T>似乎与除OData之外的任何格式化程序一起工作,那么这是巧合而不是故意的。

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. 好消息是,没有什么可以阻止你为JSON定义自己的PATCH格式,如果没有人编写一个更适合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. 我们可能会在未来的Web API版本中重新进行修补,并尝试提出一个适用于格式化程序的一致故事。

Thanks to Youssef for investigating and discovering why things weren't working. 感谢Youssef调查和发现为什么事情不起作用。 Hopefully that can get solved down the line. 希望能够解决这个问题。

I managed to crack this myself in the end after poring over the oData package source. 在仔细研究oData包源之后,我设法自己解决了这个问题。 I chose to implement another MediaTypeFormatter that wraps up the logic as it provides easy access tio HttpContent, but there are other ways to achieve this. 我选择实现另一个包含逻辑的MediaTypeFormatter,因为它提供了对HttpContent的轻松访问,但还有其他方法可以实现这一点。

The key part was figuring out how to interpret the code first model, see the commented line below: 关键部分是弄清楚如何解释代码的第一个模型,请参阅下面的注释行:

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; 
}

Hope this saves someone some trouble! 希望这可以节省一些人的麻烦!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM