Microsoft.AspNetCore.OData v9.3.0, .NET v8.0, Visual Studio 2022
I am trying to make a Patch with Delta, but it seems it doesn't work.
I created a straightforward project to test this.
Problem: delta.GetUpdatedProperties().ToLits()
is always empty. Therefore, the function delta.Update()
doesn't do anything; it doesn't do any update.
Can anybody point me in the right direction?
The call:
Query: customerId=1
Body:{"name": "XXX"}
The response I get:
{
"customerId": 1,
"name": "Test"
}
Expected response:
{
"customerId": 1,
"name": "XXX"
}
This is my controller:
[ApiController()]
[Route("odata/[controller]")]
public class CustomerController: ODataController
{
[HttpPatch]
[Produces<Customer>]
public IActionResult Patch([FromQuery] int customerId, [FromBody] Delta<Customer> delta)
{
// let's say we get this customer from the database
Customer c = new Customer();
c.Id = customerId;
c.Name = "Test";
var updatedProps = delta.GetChangedPropertyNames().ToList();
Debug.WriteLine($"Updated properties: [{string.Join(", ", updatedProps)}]"); // this is always be empty
delta.Patch(c);
return Ok(c);
}
}
This is my Program.cs
using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;
using Test;
var builder = WebApplication.CreateBuilder(args);
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Customer>("Customers");
builder.Services
.AddControllers()
.AddOData(options => options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null)
.AddRouteComponents("odata", modelBuilder.GetEdmModel()))
.AddJsonOptions(cfg => cfg.JsonSerializerOptions.PropertyNameCaseInsensitive = true);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapControllers());
app.UseSwagger();
app.UseSwaggerUI();
app.Run();
And this is the model:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
You have an inconsistency between the route names. By OData convention, you said to use "Customers", but your controller's name is the singular form, "Customer". The route is being resolved because you have added all of the attributes to expose it, but it is not being treated as an OData route.
If you want to use OData conventions, change your controller to CustomersController
. You can remove all of the attributes on the controller class. In Program.cs, change the app.UseEndPoints(...)
to simply app.MapControllers()
.
I would also recommend changing the return of the patch method to Updated(c)
. This will not return the updated customer by default, but the client can request it by including a Prefer
header with the value return=representation
.