0

I have created a very simple API, which adds "Opportunities" to my database. That works fine, here is my controller method:

[HttpPost("addopportunity")]
public async Task<IActionResult> AddOpportunityAsync([FromBody]Opportunity opp)
{
    try
    {
        await _opportunitiesRepository.AddOpportunityAsync(opp);
        return new OkObjectResult("Opportunity Created");
    }
    catch (Exception ex)
    {
        return new BadRequestObjectResult(ex.Message);
    }
}

I now want to extend my Opportunity class to include a list of materials with the opportunity. Here is my (simplified) updated Opportunity class:

public class Opportunity
{
    public long Id { get; set; }
    public DateTime DateCreated { get; set; }
    public virtual IEnumerable<OpportunityMaterial> MaterialList { get; set; } = Enumerable.Empty<OpportunityMaterial>();
}

And my OpportunityMaterial class:

public class OpportunityMaterial
{
    public long OpportunityMaterialId { get; set; }

    public long FkOpportunityId { get; set; }
    public string MaterialId { get; set; }
    public decimal Quantity { get; set; }
    public decimal QuotedPrice { get; set; }
    public decimal CompetitorPrice { get; set; }
    public virtual Opportunity FkOpportunity { get; set; }
}

Finally the change to my dbContext:

public virtual DbSet<Opportunity> Opportunities { get; set; }
public virtual DbSet<OpportunityMaterial> Materials { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{
    modelBuilder.Entity<Opportunity>(entity =>
    {
    });

    modelBuilder.Entity<OpportunityMaterial>(entity =>
    {
        entity.HasOne(d => d.FkOpportunity).WithMany(p => p.MaterialList)
            .HasForeignKey(d => d.FkOpportunityId)
            .OnDelete(DeleteBehavior.ClientSetNull)
            .HasConstraintName("FK_Opportunities_Materials");
    });
}

Now, when I submit a Post (I am using Swagger) I get the following error:

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-7e225c0f43c590e79d808df171998542-6b8ff60db4c321c6-00",
"errors": {
    "opp": [
      "The opp field is required."
           ],
"$.materialList[0].fkOpportunity": [
  "The JSON value could not be converted to DataModels.Microservice.Models.Opportunities.Opportunity. Path: $.materialList[0].fkOpportunity | LineNumber: 24 | BytePositionInLine: 31."
        ]
    }
}

I assumed that FromBody would be clever enough to deal with the child objects, or maybe it is and I am missing something else. Any guidance gratefully received.

****EDIT To try and fault find I added another POST to my controller to try to insert a Material on it's own. Here is the JSON that Swagger gave me:

{
"opportunityMaterialId": 0,
"materialId": "string",
"quantity": 0,
"quotedPrice": 0,
"competitorPrice": 0,
"opportunity": {
    "id": 1,
    "dateCreated": "2023-05-03T08:51:04.927Z",
    "monthString": "string",
    "weekOpp": 0,
    "status": "string",
    "wonLostReason": "string",
    "customer": "string",
    "site": "string",
    "county": "string",
    "notes": "string",
    "startDate": "2023-05-03T08:51:04.928Z",
    "endDate": "2023-05-03T08:51:04.928Z",
    "contactName": "string",
    "yearOpp": 0,
    "sourceNotExistingCustomer": "string",
    "materials": [
        "string"
        ]
    }
}

To my very inexperienced eye, it looks like a bit of catch 22, so when it's putting in the Material, it is also trying to put in an Opportunity to go with it. This results in a similar error to the original one. Maybe this is how it's supposed to look and how EF handles the relationship, but I have clearly got something very wrong here.

SkinnyPete63
  • 597
  • 1
  • 5
  • 20
  • It would help if you could update the question with the actual JSON input. It looks like that error says some values are not valid – Jonathan May 02 '23 at 19:39

1 Answers1

0

Whilst I can't post a comprehensive answer, I found this blog: https://code-maze.com/net-core-web-development-part5/ (and associated parts) which has provided an excellent step by step guide to resolving my issue.

SkinnyPete63
  • 597
  • 1
  • 5
  • 20