From 127a60b6217a198b264ec16ec8a5beff2b9147d2 Mon Sep 17 00:00:00 2001 From: franc Date: Wed, 9 Apr 2025 15:37:44 +0200 Subject: [PATCH] Refactoring some Code and clean Code --- .../Controller/Category/CategoryController.cs | 17 ++---- .../MediaFile/MediaFileController.cs | 32 +++++++++- .../Controller/Recipe/RecipeController.cs | 51 ++++++++-------- .../ShoppingList/ShoppingListController.cs | 12 +--- .../RecipeShoppingList/RecipeShoppingList.cs | 2 +- .../CreateOrAddIngredientRequestModel.cs | 9 +++ Francesco.Recipes.World/Program.cs | 4 +- .../Category/CategoryRepository.cs | 7 +++ .../Category/ICategoryRepository.cs | 2 + .../Repositories/Favorit/FavoritRepository.cs | 2 +- ...itRepository.cs => IFavoriteRepository.cs} | 2 +- .../Ingredient/IngredientRepository.cs | 2 - .../Instruction/IInstructionRepository.cs | 3 +- .../Instruction/InstructionRepository.cs | 29 +++++---- .../MediaFile/IMediaFileRepository.cs | 2 +- .../MediaFile/MediaFileRepository.cs | 60 +++++++------------ .../Repositories/Recipe/IRecipeRepository.cs | 2 +- .../Repositories/Recipe/RecipeRepository.cs | 6 +- .../ShoppingList/ShoppingListRepository.cs | 2 - 19 files changed, 132 insertions(+), 114 deletions(-) create mode 100644 Francesco.Recipes.World/Models/CreateOrAddIngredientRequestModel.cs rename Francesco.Recipes.World/Repositories/Favorit/{IFavoritRepository.cs => IFavoriteRepository.cs} (89%) diff --git a/Francesco.Recipes.World/Controller/Category/CategoryController.cs b/Francesco.Recipes.World/Controller/Category/CategoryController.cs index 29b06b5..f077af7 100644 --- a/Francesco.Recipes.World/Controller/Category/CategoryController.cs +++ b/Francesco.Recipes.World/Controller/Category/CategoryController.cs @@ -1,13 +1,8 @@ namespace Francesco.Recipes.World.Controller.Category { - using Francesco.Recipes.World.Models.BackendModels.Category; - using Francesco.Recipes.World.Models.BackendModels.Recipe; using Francesco.Recipes.World.Repositories.Category; using Microsoft.AspNetCore.Mvc; - [ValidateAntiForgeryToken] - [Route("Category")] - public class CategoryController : Controller { private readonly ICategoryRepository _categoryRepository; @@ -19,7 +14,7 @@ // GET: /Category [HttpGet] - public async Task>> Index() + public async Task Index() { var categories = await _categoryRepository.GetAllCategoriesAsync(); return View(categories); @@ -29,16 +24,16 @@ [HttpGet("{id:guid}")] public async Task Details(Guid id) { - var category = await _categoryRepository.GetCategoryByIdAsync(id); - return View(category); + var category = await _categoryRepository.GetCategoryByIdAsync(id); + return View(category); } // GET: /Category/{id}/recipes [HttpGet("{id:guid}/recipes")] - public async Task>> GetRecipesByCategory(Guid id) + public async Task GetRecipesByCategory(Guid id) { - var recipes = await _categoryRepository.GetRecipesByCategoryAsync(id); - return View(recipes); + var recipes = await _categoryRepository.GetRecipesByCategoryAsync(id); + return Ok(recipes); } } } diff --git a/Francesco.Recipes.World/Controller/MediaFile/MediaFileController.cs b/Francesco.Recipes.World/Controller/MediaFile/MediaFileController.cs index 14f59fe..f021a8f 100644 --- a/Francesco.Recipes.World/Controller/MediaFile/MediaFileController.cs +++ b/Francesco.Recipes.World/Controller/MediaFile/MediaFileController.cs @@ -4,9 +4,7 @@ using Francesco.Recipes.World.Repositories.MediaFile; using Microsoft.AspNetCore.Mvc; - [ValidateAntiForgeryToken] - - [Route("categories/{categoryId}/Recipe")] + [Route("Category/{categoryId}/Recipe")] public class MediaFileController : Controller { private readonly IMediaFileRepository _mediaFileRepository; @@ -20,6 +18,7 @@ // POST: /UploadImage [HttpPost("UploadImage")] + [AutoValidateAntiforgeryToken] public async Task UploadImage(Guid recipeId, IFormFile? mediaFile) { if (mediaFile is null) @@ -44,5 +43,32 @@ { return View(); } + + [HttpPost("ReplaceInstructionImage")] + [ValidateAntiForgeryToken] + public async Task ReplaceInstructionImage(Guid instructionId, Guid mediaFileIdToReplace, IFormFile? newPhoto) + { + if (newPhoto is null) + { + return BadRequest("Photo is required."); + } + + using (var memoryStream = new MemoryStream()) + { + await newPhoto.CopyToAsync(memoryStream); + + var newMediaData = memoryStream.ToArray(); + + try + { + await _mediaFileRepository.ReplaceInstructionImageAsync(instructionId, mediaFileIdToReplace, newPhoto.FileName, newPhoto.ContentType, newMediaData); + return Ok("Image replaced successfully."); + } + catch (Exception ex) + { + return StatusCode(500, $"Internal server error: {ex.Message}"); + } + } + } } } diff --git a/Francesco.Recipes.World/Controller/Recipe/RecipeController.cs b/Francesco.Recipes.World/Controller/Recipe/RecipeController.cs index 05d99aa..b86ef61 100644 --- a/Francesco.Recipes.World/Controller/Recipe/RecipeController.cs +++ b/Francesco.Recipes.World/Controller/Recipe/RecipeController.cs @@ -1,6 +1,5 @@ namespace Francesco.Recipes.World.Controller.Recipe { - using System.ComponentModel.DataAnnotations; using Francesco.Recipes.World.Models.BackendModels.Recipe; using Francesco.Recipes.World.Repositories.Category; using Francesco.Recipes.World.Repositories.Favorit; @@ -14,8 +13,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; - [ValidateAntiForgeryToken] - [Route("Recipe")] public class RecipeController : Controller { private readonly IRecipeRepository _recipeRepository; @@ -24,13 +21,18 @@ private readonly IIngredientRepository _ingredientRepository; private readonly IMediaFileRepository _mediaFileRepository; private readonly IInstructionRepository _instructionRepository; - private readonly IFavoritRepository _favoritRepository; + private readonly IFavoriteRepository _favoriteRepository; - [Display(Name = "Schwierigkeitsgrad")] - [BindProperty(SupportsGet = true)] - public Difficulty? SelectedDifficulty { get; set; } + public IReadOnlyCollection Recipes { get; set; } - public RecipeController(IRecipeRepository recipeRepository, IUnitRepository unitRepository, ICategoryRepository categoryRepository, IIngredientRepository ingredientRepository, IMediaFileRepository mediaFileRepository, IInstructionRepository instructionRepository, IFavoritRepository favoritRepository) + public RecipeController( + IRecipeRepository recipeRepository, + IUnitRepository unitRepository, + ICategoryRepository categoryRepository, + IIngredientRepository ingredientRepository, + IMediaFileRepository mediaFileRepository, + IInstructionRepository instructionRepository, + IFavoriteRepository favoriteRepository) { _recipeRepository = recipeRepository; _unitRepository = unitRepository; @@ -39,11 +41,9 @@ Recipes = new List(); _mediaFileRepository = mediaFileRepository; _instructionRepository = instructionRepository; - _favoritRepository = favoritRepository; + _favoriteRepository = favoriteRepository; } - public IReadOnlyCollection Recipes { get; set; } - // GET: /Recipe/{recipeId}/AddOrCreateIngredient [HttpGet("{recipeId}/AddOrCreateIngredient")] public async Task AddOrCreateIngredient(Guid recipeId) @@ -71,24 +71,20 @@ [HttpGet("CategoryRecipes")] public async Task CategoryRecipes() { - var categories = await _categoryRepository.GetAllCategoriesAsync(); - var viewModel = new List(); + var categories = await _categoryRepository.GetAllCategoriesWithRecipesAsync(); - foreach (var category in categories) + var viewModel = categories.Select(c => new CategoryRecipesViewModel { - var recipes = await _categoryRepository.GetRecipesByCategoryAsync(category.Id); - viewModel.Add(new CategoryRecipesViewModel - { - Category = category, - Recipes = recipes, - }); - } + Category = c, + Recipes = c.Recipes, + }).ToList(); return View(viewModel); } // POST: /Recipe/{recipeId}/AddOrCreateIngredient [HttpPost("{recipeId}/AddOrCreateIngredient")] + [ValidateAntiForgeryToken] public async Task AddOrCreateIngredient(Guid recipeId, string ingredientName, int quantity, Guid unitId) { if (quantity <= 0) @@ -123,6 +119,7 @@ // POST: /Recipe/Create/{categoryId} [HttpPost("Create/{categoryId}")] + [AutoValidateAntiforgeryToken] public async Task Create(Guid categoryId, string name, string description, Difficulty difficulty, int servings, TimeSpan preparationTime, TimeSpan cookingTime, IFormFile? photo) { if (string.IsNullOrWhiteSpace(name)) @@ -153,6 +150,7 @@ return NotFound($"Kategorie mit ID {categoryId} wurde nicht gefunden."); } + await _recipeRepository.CreateRecipeForCategoryAsync(categoryEntity, name, description, difficulty, servings, preparationTime, cookingTime); var recipe = await _recipeRepository.CreateRecipeForCategoryAsync(categoryEntity, name, description, difficulty, servings, preparationTime, cookingTime); if (photo != null) { @@ -176,13 +174,13 @@ ViewBag.RecipeId = recipeId; ViewBag.IngredientId = ingredientId; - ViewBag.IngredientName = ingredient.Name; return View(); } // POST: /Recipe/{recipeId}/RemoveIngredient/{ingredientId} [HttpPost("{recipeId}/RemoveIngredient/{ingredientId}")] + [ValidateAntiForgeryToken] public async Task RemoveIngredientConfirmed(Guid recipeId, Guid ingredientId) { await _recipeRepository.RemoveIngredientFromRecipeAsync(recipeId, ingredientId); @@ -219,6 +217,7 @@ // POST: /Recipe/{recipeId}/AddInstruction [HttpPost("{recipeId}/AddInstruction")] + [ValidateAntiForgeryToken] public async Task AddInstruction(Guid recipeId, string description, int number) { try @@ -239,23 +238,25 @@ [HttpGet("Favorites")] public async Task Favorites() { - var favoriteRecipes = await _favoritRepository.GetFavoriteRecipesAsync(); + var favoriteRecipes = await _favoriteRepository.GetFavoriteRecipesAsync(); return View(favoriteRecipes); } // POST: /Recipe/AddFavorite [HttpPost("AddFavorite")] + [ValidateAntiForgeryToken] public async Task AddFavorite(Guid recipeId) { - await _favoritRepository.AddFavoriteAsync(recipeId); + await _favoriteRepository.AddFavoriteAsync(recipeId); return RedirectToAction("Details", new { recipeId }); } // POST: /Recipe/RemoveFavorite [HttpPost("RemoveFavorite")] + [ValidateAntiForgeryToken] public async Task RemoveFavorite(Guid recipeId) { - await _favoritRepository.RemoveFavoriteAsync(recipeId); + await _favoriteRepository.RemoveFavoriteAsync(recipeId); return RedirectToAction("Details", new { recipeId }); } } diff --git a/Francesco.Recipes.World/Controller/ShoppingList/ShoppingListController.cs b/Francesco.Recipes.World/Controller/ShoppingList/ShoppingListController.cs index 7f6a434..7747880 100644 --- a/Francesco.Recipes.World/Controller/ShoppingList/ShoppingListController.cs +++ b/Francesco.Recipes.World/Controller/ShoppingList/ShoppingListController.cs @@ -1,11 +1,11 @@ namespace Francesco.Recipes.World.Controllers { using Francesco.Recipes.World.Data; + using Francesco.Recipes.World.Models; using Francesco.Recipes.World.Repositories.ShoppingList; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; - [Route("ShoppingList")] public class ShoppingListController : Controller { private readonly IShoppingListRepository _shoppingListRepository; @@ -18,7 +18,8 @@ } [HttpPost("CreateOrAddIngredients")] - public async Task CreateOrAddIngredients([FromBody] CreateOrAddIngredientsRequest request) + [ValidateAntiForgeryToken] + public async Task CreateOrAddIngredients([FromBody] CreateOrAddIngredientRequestModel request) { if (request == null || request.IngredientIds == null || !request.IngredientIds.Any()) { @@ -39,12 +40,5 @@ return Json(new { shoppingListId = shoppingList.Id }); } - - public class CreateOrAddIngredientsRequest - { - public Guid RecipeId { get; set; } - - public List IngredientIds { get; set; } = new (); - } } } diff --git a/Francesco.Recipes.World/Models/BackendModels/RecipeShoppingList/RecipeShoppingList.cs b/Francesco.Recipes.World/Models/BackendModels/RecipeShoppingList/RecipeShoppingList.cs index 1173425..d7ba63d 100644 --- a/Francesco.Recipes.World/Models/BackendModels/RecipeShoppingList/RecipeShoppingList.cs +++ b/Francesco.Recipes.World/Models/BackendModels/RecipeShoppingList/RecipeShoppingList.cs @@ -10,7 +10,7 @@ public virtual ShoppingList ShoppingList { get; set; } = new ShoppingList(); - public virtual Recipe Recipe { get; set; } = new (); + public virtual Recipe Recipe { get; set; } = new Recipe(); public virtual ICollection SelectedIngredients { get; set; } = new List(); } diff --git a/Francesco.Recipes.World/Models/CreateOrAddIngredientRequestModel.cs b/Francesco.Recipes.World/Models/CreateOrAddIngredientRequestModel.cs new file mode 100644 index 0000000..8843bd8 --- /dev/null +++ b/Francesco.Recipes.World/Models/CreateOrAddIngredientRequestModel.cs @@ -0,0 +1,9 @@ +namespace Francesco.Recipes.World.Models +{ + public class CreateOrAddIngredientRequestModel + { + public Guid RecipeId { get; set; } + + public List IngredientIds { get; set; } = new (); + } +} diff --git a/Francesco.Recipes.World/Program.cs b/Francesco.Recipes.World/Program.cs index 6f98ff1..f5f164d 100644 --- a/Francesco.Recipes.World/Program.cs +++ b/Francesco.Recipes.World/Program.cs @@ -39,7 +39,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); var app = builder.Build(); @@ -64,6 +64,6 @@ app.MapDefaultControllerRoute(); app.MapControllerRoute( name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); + pattern: "{controller=Category}/{action=Index}/{id?}"); app.Run(); diff --git a/Francesco.Recipes.World/Repositories/Category/CategoryRepository.cs b/Francesco.Recipes.World/Repositories/Category/CategoryRepository.cs index 6e372f8..39e7228 100644 --- a/Francesco.Recipes.World/Repositories/Category/CategoryRepository.cs +++ b/Francesco.Recipes.World/Repositories/Category/CategoryRepository.cs @@ -41,5 +41,12 @@ return category.Recipes; } + + public async Task> GetAllCategoriesWithRecipesAsync() + { + return await _context.Categories + .Include(c => c.Recipes) + .ToListAsync(); + } } } diff --git a/Francesco.Recipes.World/Repositories/Category/ICategoryRepository.cs b/Francesco.Recipes.World/Repositories/Category/ICategoryRepository.cs index 04491aa..f449de0 100644 --- a/Francesco.Recipes.World/Repositories/Category/ICategoryRepository.cs +++ b/Francesco.Recipes.World/Repositories/Category/ICategoryRepository.cs @@ -13,5 +13,7 @@ Task> GetAllCategoriesAsync(); Task> GetRecipesByCategoryAsync(Guid categoryId); + + Task> GetAllCategoriesWithRecipesAsync(); } } diff --git a/Francesco.Recipes.World/Repositories/Favorit/FavoritRepository.cs b/Francesco.Recipes.World/Repositories/Favorit/FavoritRepository.cs index b4eddb5..eb8cae2 100644 --- a/Francesco.Recipes.World/Repositories/Favorit/FavoritRepository.cs +++ b/Francesco.Recipes.World/Repositories/Favorit/FavoritRepository.cs @@ -4,7 +4,7 @@ using Francesco.Recipes.World.Models.BackendModels.Recipe; using Microsoft.EntityFrameworkCore; - public class FavoritRepository : IFavoritRepository + public class FavoritRepository : IFavoriteRepository { private readonly FrancescosRecipesWorldDbContext _context; diff --git a/Francesco.Recipes.World/Repositories/Favorit/IFavoritRepository.cs b/Francesco.Recipes.World/Repositories/Favorit/IFavoriteRepository.cs similarity index 89% rename from Francesco.Recipes.World/Repositories/Favorit/IFavoritRepository.cs rename to Francesco.Recipes.World/Repositories/Favorit/IFavoriteRepository.cs index 8f47e0a..bf1fd13 100644 --- a/Francesco.Recipes.World/Repositories/Favorit/IFavoritRepository.cs +++ b/Francesco.Recipes.World/Repositories/Favorit/IFavoriteRepository.cs @@ -2,7 +2,7 @@ { using Francesco.Recipes.World.Models.BackendModels.Recipe; - public interface IFavoritRepository + public interface IFavoriteRepository { Task> GetFavoriteRecipesAsync(); diff --git a/Francesco.Recipes.World/Repositories/Ingredient/IngredientRepository.cs b/Francesco.Recipes.World/Repositories/Ingredient/IngredientRepository.cs index 69a21ed..6f85a97 100644 --- a/Francesco.Recipes.World/Repositories/Ingredient/IngredientRepository.cs +++ b/Francesco.Recipes.World/Repositories/Ingredient/IngredientRepository.cs @@ -37,7 +37,6 @@ namespace Francesco.Recipes.World.Repositories.Ingredient existingRecipeIngredient.Ingredient = recipeIngredient.Ingredient; existingRecipeIngredient.Unit = recipeIngredient.Unit; - _context.RecipeIngredients.Update(existingRecipeIngredient); await _context.SaveChangesAsync(); } @@ -77,7 +76,6 @@ namespace Francesco.Recipes.World.Repositories.Ingredient existingIngredient.Name = ingredient.Name; - _context.Ingredients.Update(existingIngredient); await _context.SaveChangesAsync(); } diff --git a/Francesco.Recipes.World/Repositories/Instruction/IInstructionRepository.cs b/Francesco.Recipes.World/Repositories/Instruction/IInstructionRepository.cs index 1d22238..963099b 100644 --- a/Francesco.Recipes.World/Repositories/Instruction/IInstructionRepository.cs +++ b/Francesco.Recipes.World/Repositories/Instruction/IInstructionRepository.cs @@ -1,7 +1,6 @@ namespace Francesco.Recipes.World.Repositories.Instruction { using Francesco.Recipes.World.Models.BackendModels.Instruction; - using Francesco.Recipes.World.Models.BackendModels.Recipe; public interface IInstructionRepository { @@ -11,6 +10,6 @@ Task> GetInstructionsByRecipeIdAsync(Guid recipeId); - Task RemoveInstructionFromRecipeAsync(Recipe recipe, Guid instructionId); + Task RemoveInstructionFromRecipeAsync(Guid recipeId, Guid instructionId); } } diff --git a/Francesco.Recipes.World/Repositories/Instruction/InstructionRepository.cs b/Francesco.Recipes.World/Repositories/Instruction/InstructionRepository.cs index 09561c5..b487d57 100644 --- a/Francesco.Recipes.World/Repositories/Instruction/InstructionRepository.cs +++ b/Francesco.Recipes.World/Repositories/Instruction/InstructionRepository.cs @@ -2,7 +2,6 @@ { using Francesco.Recipes.World.Data; using Francesco.Recipes.World.Models.BackendModels.Instruction; - using Francesco.Recipes.World.Models.BackendModels.Recipe; using Francesco.Recipes.World.Repositories.Recipe; using Microsoft.EntityFrameworkCore; @@ -25,19 +24,19 @@ public async Task CreateInstructionToRecipeAsync(Guid recipeId, string description, int number) { - var recipe = await _recipeRepository.GetRecipeAsync(recipeId); + var recipe = await _recipeRepository.GetRecipeAsync(recipeId); - if (string.IsNullOrWhiteSpace(description)) + if (string.IsNullOrWhiteSpace(description)) { throw new ArgumentException("Description cannot be empty", nameof(description)); } - if (number <= 0) + if (number <= 0) { throw new ArgumentOutOfRangeException(nameof(number), "Number must be greater than 0."); } - var newInstruction = new Instruction + var newInstruction = new Instruction { Id = Guid.NewGuid(), Description = description, @@ -45,24 +44,28 @@ Recipe = recipe, }; - _context.Instructions.Add(newInstruction); - await _context.SaveChangesAsync(); + _context.Instructions.Add(newInstruction); + await _context.SaveChangesAsync(); - return newInstruction; + return newInstruction; } - public async Task RemoveInstructionFromRecipeAsync(Recipe recipe, Guid instructionId) + public async Task RemoveInstructionFromRecipeAsync(Guid recipeId, Guid instructionId) { - if (recipe == null) + var recipe = await _recipeRepository.GetRecipeAsync(recipeId); + + if (recipe.Instructions == null || !recipe.Instructions.Any()) { - throw new ArgumentNullException(nameof(recipe)); + await _context.Entry(recipe) + .Collection(r => r.Instructions) + .LoadAsync(); } - var instructionToRemove = recipe.Instructions.FirstOrDefault(i => i.Id == instructionId); + var instructionToRemove = recipe.Instructions?.FirstOrDefault(i => i.Id == instructionId); if (instructionToRemove != null) { - recipe.Instructions.Remove(instructionToRemove); + recipe.Instructions?.Remove(instructionToRemove); await _context.SaveChangesAsync(); } } diff --git a/Francesco.Recipes.World/Repositories/MediaFile/IMediaFileRepository.cs b/Francesco.Recipes.World/Repositories/MediaFile/IMediaFileRepository.cs index 879a1b2..9320d8c 100644 --- a/Francesco.Recipes.World/Repositories/MediaFile/IMediaFileRepository.cs +++ b/Francesco.Recipes.World/Repositories/MediaFile/IMediaFileRepository.cs @@ -2,7 +2,7 @@ { public interface IMediaFileRepository { - Task ReplaceInstructionImageAsync(Guid instructionId, Guid mediafileId, IFormFile? newPhoto); + Task ReplaceInstructionImageAsync(Guid instructionId, Guid mediaFileIdToReplace, string fileName, string mimeType, byte[] newMediaData); Task UploadInstructionImageAsync(Guid instructionId, IFormFile? photo); diff --git a/Francesco.Recipes.World/Repositories/MediaFile/MediaFileRepository.cs b/Francesco.Recipes.World/Repositories/MediaFile/MediaFileRepository.cs index b4beb26..15f1fc6 100644 --- a/Francesco.Recipes.World/Repositories/MediaFile/MediaFileRepository.cs +++ b/Francesco.Recipes.World/Repositories/MediaFile/MediaFileRepository.cs @@ -2,6 +2,7 @@ { using Francesco.Recipes.World.Data; using Francesco.Recipes.World.Models.BackendModels.MediaFile; + using Francesco.Recipes.World.Models.BackendModels.Recipe; using Francesco.Recipes.World.Repositories.Instruction; using Francesco.Recipes.World.Repositories.Recipe; @@ -18,13 +19,8 @@ _recipeRepository = recipeRepository; } - public async Task ReplaceInstructionImageAsync(Guid instructionId, Guid mediaFileIdToReplace, IFormFile? newPhoto) + public async Task ReplaceInstructionImageAsync(Guid instructionId, Guid mediaFileIdToReplace, string fileName, string mimeType, byte[] newMediaData) { - if (newPhoto is null) - { - throw new ArgumentNullException(nameof(newPhoto)); - } - var instruction = await _instructionRepository.GetInstructionAsync(instructionId); var mediaToReplace = instruction.MediaFiles.FirstOrDefault(m => m.Id == mediaFileIdToReplace); @@ -36,22 +32,17 @@ _context.MediaFiles.Remove(mediaToReplace); await _context.SaveChangesAsync(); - using (var memoryStream = new MemoryStream()) + var newMedia = new MediaFile { - await newPhoto.CopyToAsync(memoryStream); + Id = Guid.NewGuid(), + FileName = fileName, + MimeType = mimeType, + Data = newMediaData, + Instruction = instruction, + }; - var newMedia = new MediaFile - { - Id = Guid.NewGuid(), - FileName = newPhoto.FileName, - MimeType = newPhoto.ContentType, - Data = memoryStream.ToArray(), - Instruction = instruction, - }; - - _context.MediaFiles.Add(newMedia); - await _context.SaveChangesAsync(); - } + _context.MediaFiles.Add(newMedia); + await _context.SaveChangesAsync(); } public async Task UploadInstructionImageAsync(Guid instructionId, IFormFile? photo) @@ -89,11 +80,6 @@ var recipe = await _recipeRepository.GetRecipeAsync(recipeId); - if (recipe == null) - { - throw new InvalidOperationException("The specified recipe does not exist."); - } - var isImage = mediaFile.ContentType.StartsWith("image/"); var isVideo = mediaFile.ContentType.StartsWith("video/"); @@ -104,21 +90,11 @@ if (isImage) { - var existingImage = recipe.MediaFiles?.FirstOrDefault(m => m.MimeType?.StartsWith("image/") == true); - if (existingImage != null) - { - _context.MediaFiles.Remove(existingImage); - await _context.SaveChangesAsync(); - } + await RemoveExistingMediaAsync(recipe, "image/"); } else if (isVideo) { - var existingVideo = recipe.MediaFiles?.FirstOrDefault(m => m.MimeType?.StartsWith("video/") == true); - if (existingVideo != null) - { - _context.MediaFiles.Remove(existingVideo); - await _context.SaveChangesAsync(); - } + await RemoveExistingMediaAsync(recipe, "video/"); } using var memoryStream = new MemoryStream(); @@ -136,5 +112,15 @@ _context.MediaFiles.Add(newMedia); await _context.SaveChangesAsync(); } + + private async Task RemoveExistingMediaAsync(Recipe recipe, string mediaTypePrefix) + { + var existingMedia = recipe.MediaFiles?.FirstOrDefault(m => m.MimeType?.StartsWith(mediaTypePrefix) == true); + if (existingMedia != null) + { + _context.MediaFiles.Remove(existingMedia); + await _context.SaveChangesAsync(); + } + } } } diff --git a/Francesco.Recipes.World/Repositories/Recipe/IRecipeRepository.cs b/Francesco.Recipes.World/Repositories/Recipe/IRecipeRepository.cs index c5d46a0..03414e1 100644 --- a/Francesco.Recipes.World/Repositories/Recipe/IRecipeRepository.cs +++ b/Francesco.Recipes.World/Repositories/Recipe/IRecipeRepository.cs @@ -13,7 +13,7 @@ Task RemoveIngredientFromRecipeAsync(Guid recipeId, Guid ingredientId); - Task> GetRecipesByNameOrIngredientAsync(string name, string ingredient); + Task> GetRecipesByNameAndIngredientAsync(string name, string ingredient); Task> GetRecipesByDifficultyAsync(Difficulty? difficulty); diff --git a/Francesco.Recipes.World/Repositories/Recipe/RecipeRepository.cs b/Francesco.Recipes.World/Repositories/Recipe/RecipeRepository.cs index ae33b43..1b7470a 100644 --- a/Francesco.Recipes.World/Repositories/Recipe/RecipeRepository.cs +++ b/Francesco.Recipes.World/Repositories/Recipe/RecipeRepository.cs @@ -37,6 +37,7 @@ .Include(r => r.RecipeIngredients) .ThenInclude(ri => ri.Unit) .Include(r => r.MediaFiles) + .Include(r => r.Instructions) .FirstOrDefaultAsync(r => r.Id == recipeId); } @@ -53,7 +54,7 @@ var ingredients = await _ingredientRepository.GetIngredientsByNameAsync(ingredientName); Ingredient ingredient; - if (ingredients == null || !ingredients.Any()) + if (!ingredients.Any()) { ingredient = new Ingredient { @@ -131,7 +132,6 @@ public async Task RemoveIngredientFromRecipeAsync(Guid recipeId, Guid ingredientId) { - var recipe = await GetRecipeAsync(recipeId); var recipeIngredient = await _context.RecipeIngredients .FirstOrDefaultAsync(ri => ri.Recipe.Id == recipeId && ri.Ingredient.Id == ingredientId); @@ -144,7 +144,7 @@ await _context.SaveChangesAsync(); } - public async Task> GetRecipesByNameOrIngredientAsync(string name, string ingredient) + public async Task> GetRecipesByNameAndIngredientAsync(string name, string ingredient) { var query = _context.Recipes .Include(r => r.RecipeIngredients) diff --git a/Francesco.Recipes.World/Repositories/ShoppingList/ShoppingListRepository.cs b/Francesco.Recipes.World/Repositories/ShoppingList/ShoppingListRepository.cs index 45793f0..c3e8590 100644 --- a/Francesco.Recipes.World/Repositories/ShoppingList/ShoppingListRepository.cs +++ b/Francesco.Recipes.World/Repositories/ShoppingList/ShoppingListRepository.cs @@ -114,7 +114,6 @@ public async Task> GetIngredientsOfRecipeInListAsync(Guid shoppingListRecipeId) { return await _context.RecipeIngredientsShoppingLists - .AsNoTracking() .Include(i => i.RecipeIngredient) .ThenInclude(ri => ri.Ingredient) .Include(i => i.RecipeIngredient.Unit) @@ -168,7 +167,6 @@ public async Task GetRecipeByNameAndImageAsync(string recipeName, string imageFileName) { return await _context.Recipes - .AsNoTracking() .Where(r => r.Name == recipeName && r.MediaFiles.Any(mf => mf.FileName == imageFileName)) .Include(r => r.MediaFiles.Where(mf => mf.FileName == imageFileName)) .FirstOrDefaultAsync();