Mistake. Cannot apply PATCH to navigation property. So what should I do?

I have a Web API 2.2 OData 4 serving the following model using entity framework:

public class Company
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<CompanyType> CompanyTypes { get; set; }
}

public class CompanyType
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Company> Companies { get; set; }
}

      

And a little bit of smooth display:

modelBuilder.Entity<Company>().HasMany(x => x.CompanyTypes).WithMany(x => x.Companies).Map(x =>
{
  x.MapLeftKey("CompanyId");
  x.MapRightKey("CompanyTypeId");
  x.ToTable("CompaniesCompanyTypes");
});

      

On my CompanysController I have a patch method and I hope you can submit the following request and successfully update the company name and create a couple of company type records for that company:

PATCH http://localhost:50113/MessagingService/odata//CompanyDTOs(1)/ HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-16
Host: localhost:50113
Content-Length: 174

{"Name":"Cheesy Peas Ltd","CompanyTypes":[{"Id":1,"Name":"Parent"},{"Id":2,"Name":"Subsidiary"}]}

      

But I am getting:

{
  "error":{
    "code":"","message":"The request is invalid.","innererror":{
      "message":"delta : Cannot apply PATCH to navigation property 'CompanyTypes' on entity type 'Core.Models.Company'.\r\n","type":"","stacktrace":""
    }
  }
}

      

I am guessing that I am asking too much of my PATCH request, but does anyone have any suggestion on how I should achieve this? The simpler the better - I don't want to add complexity to my client application if I can avoid it, and would rather use PATCH over PUT.

Many thanks. If you are interested in this question and would like more information, please ask.

EDIT

Specifically, what I need is the ability to insert a record into many tables when a record is updated on a portion of that relationship. For example. If a Student has many classes and a class has many students, then when I update Student A, I can also add the link to Class One, remove the link to the second class, and leave the link to the third class.

I read the OData documentation here:

http://docs.oasis-open.org/odata/odata-atom-format/v4.0/cs02/odata-atom-format-v4.0-cs02.html#_Toc372792732

But for me this is a bit of a mystery. I'm sure there must be a way to do this using things like "@ odata.bind" etc.

Any opinions there?

+3


source to share


1 answer


Based on this workitem , you need to create a collection of primitive types instead of a complex list type.

Entity

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<ProductType> ProductTypes { get; set; }
}
public class ProductDto : Product
{
    public ICollection<int> ProductTypeIds { get; set; }
    public ICollection<string> ProductTypeNames { get; set; }
}
public class ProductType
{
    public int Id { get; set; }
    public string Name { get; set; }
}

      

Act

// PATCH odata/Products(5)
[AcceptVerbs("PATCH", "MERGE")]
public IHttpActionResult Patch([FromODataUri] int key, Delta<ProductDto> patch)
{
    object productTypeIds;
    patch.TryGetPropertyValue("ProductTypeIds", out productTypeIds);
    object productTypeNames;
    patch.TryGetPropertyValue("ProductTypeNames", out productTypeNames);

    // TODO: Implement update to database.

    return Updated(new ProductDto()); // for demo purpose
}

      

Config



ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
builder.EntitySet<ProductDto>("ProductDtos");
builder.EntitySet<ProductType>("ProductType");
config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());

      

Violinist

PATCH http://localhost:59829/odata/Products(1) HTTP/1.1

User-Agent: Fiddler
Host: localhost:59829
Content-Length: 83
Content-Type: application/json

{"Id":1, "Name":"A", "ProductTypeIds":[1,2], "ProductTypeNames":["AA", "BB"] }

      

Result

Result

Hope it helps.

+4


source







All Articles