4

From JavaScript client code I am creating the following data:

    var employee = {
        FirstName: "Rudolf",
        Salary: 99
    };

I then pass this through an Ajax call to an MVC Web API Controller Action:

using System.Web.Http.OData;

    public async Task<IHttpActionResult> Patch([FromUri] int employeeId, [FromBody] Delta<Employee> employee)
    {
        await _employeeService.Patch(employeeId, employee);
        return Ok();
    }

This calls my service to update the database as follows:

    public async Task Patch(int employeeId, Delta<Employee> employee)
    {
        using (var context = new DBEntities())
        {
            if (employee.TryGetPropertyValue("Salary", out object salary))
            {
                var ss = Convert.ToDouble(salary); // Always 0
            }

            if (employee.TryGetPropertyValue("FirstName", out object firstName))
            {
                var ss = Convert.ToString(firstName); // Expected value
            }

            var currentEmployee = await context.Employees
                .FirstOrDefaultAsync(e => e.Id == employeeId);

            if (currentEmployee == null)
                return;

            employee.Patch(currentEmployee);

            await context.SaveChangesAsync();
        }
    }

Note: I missed out some of the details for brevity as the actual client-server call is working fine.

The code seems to work as expected, but the Salary property (the only none-string one) is always set to 0 (zero). So that field never get's updated.

Any ideas why the Salary is not being passed through?

Note: I use very similar client-server code for GET/POST/PUT/DELETE and they all work fine, so I believe it is related to the Delta<> part.

Rob L
  • 2,124
  • 3
  • 22
  • 50

2 Answers2

3

Yes, I encountered the same problem with int properties.

I solved the problem using SimplePatch (v1.0 is only 10KB).

Disclaimer: I'm the author of the project.

It is inspired to Microsoft.AspNet.WebApi.OData but SimplePatch has no dependencies.

How to use Install the package using:

Install-Package SimplePatch

Your MVC Web API Controller Action becomes:

using SimplePatch;

public async Task<IHttpActionResult> Patch([FromUri] int employeeId, [FromBody] Delta<Employee> employee)
{
    await _employeeService.Patch(employeeId, employee);
    return Ok();
}

Then your Patch method becomes:

public async Task Patch(int employeeId, Delta<Employee> employee)
{
    using (var context = new DBEntities())
    {
        if (employee.TryGetPropertyValue("Salary", out object salary))
        {
            var ss = Convert.ToDouble(salary);
        }

        if (employee.TryGetPropertyValue("FirstName", out object firstName))
        {
            var ss = Convert.ToString(firstName);
        }

        var currentEmployee = await context.Employees
            .FirstOrDefaultAsync(e => e.Id == employeeId);

        if (currentEmployee == null)
            return;

        employee.Patch(currentEmployee);

        await context.SaveChangesAsync();
    }
}

Also, SimplePatch gives you the ability to ignore some properties when calling the Patch method.

Global.asax or Startup.cs

DeltaConfig.Init((cfg) =>
{
    cfg.ExcludeProperties<Employee>(x => x.YourPropertyName);
});
Omar Muscatello
  • 1,256
  • 14
  • 25
2

If Salary has type int then there is an issue with that type

The Json parser converts integers to 64 bit ones, which won't match the 32 bit int properties declared on the entity and thus get ignored by this method.

This problem is mentioned here

So, you can use long instead of int or using the OData media type formatters See this

Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116