0

I have 3 tables in my database: Ingredient, IngredientRecipe and Recipe. Adding data to Ingredient works correctly. IngredientRecipe is for making relation between Ingredient and Recipe. When I want to add a Recipe to database, nothing happens. No errors, no data in the database.

My error message:

System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.

DbContext class:

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<Ingredient> IngredientsTable { get; set; }
    public DbSet<IngredientRecipe> IngredientRecipesTable { get; set; }
    public DbSet<Recipe> RecipesTable { get; set; }
}

Ingredient, IngredientRecipe and Recipe:

public class Ingredient : BaseEntity
{
    public string Name { get; set; }
    public int Kcal { get; set; }

    public virtual ICollection<IngredientRecipe> IngredientRecipe { get; set; }
}

public class IngredientRecipe : BaseEntity
{
    public int IngredientId { get; set; }
    public int RecipeId { get; set; }
    public int Amount { get; set; }

    public Ingredient Ingredient { get; set; }
    public Recipe Recipe { get; set; }
}

public class Recipe : BaseEntity
{
    public string Name { get; set; }

    public List<IngredientRecipe> ListOfIngredients { get; set; }
}

And here is my form code:

@page "/recipes/create"
@inject IIngredientRepository ingredientRepository
@inject IRecipeRepository recipeRepository
@inject NavigationManager navManager

<div class="container col-12">
    <EditForm Model="Recipe" OnValidSubmit="SaveRecipe">
        <button class="btn btn-primary">Save recipe</button>
        <div class="col-4">
            <div class="form-control">
                <InputText @bind-Value="Recipe.Name" />
            </div>
        </div>
    </EditForm>
</div>
<div class="row">
    <div class="col-6">
        <TableTemplate Items="ListOfIngredients">
            <TableHeader>
                <th>Name</th>
                <th>Kcal</th>
                <th>Action</th>
            </TableHeader>
            <RowTemplate Context="ingredient">
                <td>@ingredient.Name</td>
                <td>@ingredient.Kcal</td>
                <td>
                    <button class="btn btn-primary" @onclick="@(()=>SetTheAmount(ingredient))">Add</button>
                </td>
            </RowTemplate>
        </TableTemplate>
    </div>
    <div class="col-6">
        List of ingredients
        <br />
        @if (ListOfIngredientAmounts.Any())
        {
            <TableTemplate Items="ListOfIngredientAmounts">
                <TableHeader>
                    <th>Name</th>
                    <th>Amount</th>
                    <th>Action</th>
                </TableHeader>
                <RowTemplate Context="ingredient">
                    <td>@ingredient.Ingredient.Name</td>
                    <td>@ingredient.Amount</td>
                    <td>
                        <button class="btn btn-primary">Delete</button>
                    </td>
                </RowTemplate>
            </TableTemplate>
        }
    </div>
</div>

@if (IngredientAmount.Ingredient != null)
{
    <p>Ingredient Id: @IngredientAmount.IngredientId | Name: @IngredientAmount.Ingredient.Name | Amount: @IngredientAmount.Amount</p>
    <EditForm Model="IngredientAmount" OnValidSubmit="AddIngredientToIngredientAmountList">
        <div class="form-group">
            Value
            <InputNumber @bind-Value="IngredientAmount.Amount" />
        </div>
        <button class="btn btn-primary" type="submit">Add to list</button>
    </EditForm>
}

@code{
    public Recipe Recipe { get; set; } = new Recipe();

    public List<Ingredient> ListOfIngredients { get; set; } = new List<Ingredient>();

    public IngredientRecipe IngredientAmount { get; set; } = new IngredientRecipe();

    public List<IngredientRecipe> ListOfIngredientAmounts { get; set; } = new List<IngredientRecipe>();

    protected override async Task OnInitializedAsync()
    {
        ListOfIngredients = await ingredientRepository.GetListOfIngredients();
    }

    private void SetTheAmount(Ingredient ingredient)
    {
        IngredientAmount = new IngredientRecipe();
        IngredientAmount.IngredientId = ingredient.Id;
        IngredientAmount.Recipe = Recipe;
        IngredientAmount.RecipeId = Recipe.Id;
        IngredientAmount.Ingredient = ingredient;
    }

    private void AddIngredientToIngredientAmountList()
    {
        ListOfIngredientAmounts.Add(IngredientAmount);
        IngredientAmount = new IngredientRecipe();
    }

    private async void SaveRecipe()
    {
        if (ListOfIngredientAmounts.Any())
        {
            Recipe.ListOfIngredients = ListOfIngredientAmounts;

            await recipeRepository.CreateRecipe(Recipe);

            ListOfIngredientAmounts = new List<IngredientRecipe>();
            Recipe = new Recipe();
            navManager.NavigateTo("/recipes");
        }
    }
}

And my repository and controller responsible for post:

public async Task CreateRecipe(Recipe recipe)
{
        var response = await httpClient.PostAsJsonAsync(url, recipe);

        if (!response.IsSuccessStatusCode)
        {
            throw new ApplicationException(await response.Content.ReadAsStringAsync());
        }
}


[HttpPost]
public async Task<ActionResult<int>> Post(Recipe recipe)
{
    context.RecipesTable.Add(recipe);
    await context.SaveChangesAsync();
    return recipe.Id;
}

And here is link to GitHub https://github.com/szymonJag/CookBook

8
  • 1
    You aren't checking for an Exception on SaveChangesAsync() so how do you know there aren't any errors? Commented Jan 19, 2021 at 17:48
  • Could you expand? I change code like this but i dont know if i did it correctly try { await context.SaveChangesAsync(); } catch(Exception e) { Console.WriteLine($"{e} exception");} Commented Jan 19, 2021 at 18:01
  • See here for a discussion about exception handling with SaveChangesAsync() Commented Jan 19, 2021 at 18:09
  • Still dont know if i did it correctly try { await context.SaveChangesAsync(); } catch(DbUpdateConcurrencyException) { throw; } Please correct me if it is possible Commented Jan 19, 2021 at 18:33
  • So, drop a breakpoint on SaveChangesAsync() and step through your code. Is it throwing an Exception? Commented Jan 19, 2021 at 18:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.