Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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. 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/

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.

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.

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:

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 }
like image 424
beyond-code Avatar asked Feb 06 '13 12:02

beyond-code


2 Answers

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.

like image 60
Youssef Moussaoui Avatar answered Nov 09 '22 23:11

Youssef Moussaoui


Thanks to Youssef for investigating and discovering why things weren't working. Hopefully that can get solved down the line.

I managed to crack this myself in the end after poring over the oData package source. 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.

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!

like image 45
beyond-code Avatar answered Nov 09 '22 21:11

beyond-code