Home > OS >  OData Controller Get and Post actions for many to many entity
OData Controller Get and Post actions for many to many entity

Time:09-01

Can anyone point me to sample Controller code for Get and Post actions for a many-to-many entity?

I'm using a test project with .Net6 core EF6 core Odata8 core.

I've got other entity relations working fine and from what I can see online the examples appear to be for older cold referring to links where now I believe it might be achieved using $ref?

I have a company entity which can have many categories. I don't need additional columns in the join table. Just looking for the basic controller examples to help me stitch it together.

company entity

namespace Reviews.Entities
{
    public class Company
    {
        [Key]
        public int CompanyId { get; set; }

        [StringLength(100)]
        public string? CompanyName { get; set; } = null!;

      <shortened for brevity>

        public Rating? Rating { get; set; }

 
        public ICollection<Category>? Categories { get; set; }
    }
}
categories entity

namespace Reviews.Entities
{
    public class Category
    {
        [Key]
        public int CategoryId { get; set; }

        [Required]
        [StringLength(100)]
        public string CategoryName { get; set; } = null!;

     <shortened for brevity>        

        public ICollection<Company>? Companies{ get; set; }
    }
}
DbContext.cs

    modelBuilder
        .Entity<Company>()
        .HasMany(p => p.Categories)
        .WithMany(p => p.Companies)
        .UsingEntity(j => j.ToTable("CompanyCategories"));

Any pointers/samples to push me in the right direction welcome!!

Thanks

CodePudding user response:

After much trawling of the interwebs and reading, and testing I finally worked it out. Could probably be improved but including my solution here to help others.

The clue is in the docs but there are some issues trying to run this with the latest libraries on .Net core 6 so I kept digging.

The $ref approach appears to be the OData standard way with a few support combinations of the Uri.

CompaniesController.cs
<snippet>
        // POST: ~/Companies(1)/Categories(1)/$ref
        [HttpPost("odata/v1/Companies({key})/Categories({relatedkey})/$ref")]
        public async Task<IActionResult> CreateRef(int key, [FromODataUri] int relatedkey)
        {
            var company = await _reviewsDbContext.Companies.Include( p => p.Categories).SingleOrDefaultAsync(p => p.CompanyId == key);
            if (company == null)
            {
                return NotFound();
            }

            var category = await _reviewsDbContext.Categories.SingleOrDefaultAsync(c => c.CategoryId == relatedkey);
            if (category == null)
            {
                return NotFound();
            }
                       
            company.Categories.Add(category);
            await _reviewsDbContext.SaveChangesAsync();
            return Ok(category);
        }
      // DELETE
        [HttpDelete("odata/v1/Companies({key})/Categories({relatedkey})/$ref")]
        public async Task<IActionResult> DeleteRef(int key, [FromODataUri] int relatedkey)
        {
            var company = await _reviewsDbContext.Companies.Include(p => p.Categories).SingleOrDefaultAsync(p => p.CompanyId == key);
            if (company == null) 
            {
                return NotFound();
            }

            var category = await _reviewsDbContext.Categories.SingleOrDefaultAsync(p => p.CategoryId == relatedkey);                 
            if (category == null)
            {
                return NotFound();
            }

            var currentCategories = company.Categories
                .Where(c => c.CategoryId == relatedkey).ToList();
            
            if (currentCategories == null)
            {
                return Ok(false);
            }

            for(int i=0; i< currentCategories.Count; i  )
            {
                company.Categories.Remove(currentCategories[i]);
            }

            if (await _reviewsDbContext.SaveChangesAsync() > 0)
            {
                return NoContent(); ;
            } else
            {
                return Ok(false);
            }
        }
  • Related