Browse Source

inital commit

Axel Nordh 6 months ago
commit
2d79cc33e4
100 changed files with 2931 additions and 0 deletions
  1. 106 0
      .github/copilot-instructions.md
  2. 21 0
      .vscode/tasks.json
  3. 31 0
      Controllers/HomeController.cs
  4. 362 0
      Controllers/RecipeController.cs
  5. 100 0
      Data/RecipeContext.cs
  6. 8 0
      Models/ErrorViewModel.cs
  7. 12 0
      Models/Ingredient.cs
  8. 34 0
      Models/Recipe.cs
  9. 17 0
      Models/RecipeImage.cs
  10. 18 0
      Models/RecipeIngredientLink.cs
  11. 17 0
      Models/RecipeStep.cs
  12. 35 0
      Program.cs
  13. 38 0
      Properties/launchSettings.json
  14. 135 0
      README.md
  15. 20 0
      Recepie.csproj
  16. 24 0
      Recepie.sln
  17. 20 0
      ViewModels/RecipeIndexViewModel.cs
  18. 8 0
      Views/Home/Index.cshtml
  19. 6 0
      Views/Home/Privacy.cshtml
  20. 68 0
      Views/Recipe/Create.cshtml
  21. 51 0
      Views/Recipe/Delete.cshtml
  22. 188 0
      Views/Recipe/Details.cshtml
  23. 67 0
      Views/Recipe/Edit.cshtml
  24. 170 0
      Views/Recipe/Index.cshtml
  25. 60 0
      Views/Recipe/InspectDatabase.cshtml
  26. 14 0
      Views/Recipe/SimpleTest.cshtml
  27. 134 0
      Views/Recipe/TestDatabase.cshtml
  28. 25 0
      Views/Shared/Error.cshtml
  29. 59 0
      Views/Shared/_Layout.cshtml
  30. 48 0
      Views/Shared/_Layout.cshtml.css
  31. 2 0
      Views/Shared/_ValidationScriptsPartial.cshtml
  32. 3 0
      Views/_ViewImports.cshtml
  33. 3 0
      Views/_ViewStart.cshtml
  34. 8 0
      appsettings.Development.json
  35. 9 0
      appsettings.json
  36. BIN
      bin/Debug/net8.0/Humanizer.dll
  37. BIN
      bin/Debug/net8.0/Microsoft.Bcl.AsyncInterfaces.dll
  38. BIN
      bin/Debug/net8.0/Microsoft.Build.Locator.dll
  39. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll
  40. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.dll
  41. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll
  42. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll
  43. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.dll
  44. BIN
      bin/Debug/net8.0/Microsoft.CodeAnalysis.dll
  45. BIN
      bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll
  46. BIN
      bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Design.dll
  47. BIN
      bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Relational.dll
  48. BIN
      bin/Debug/net8.0/Microsoft.EntityFrameworkCore.dll
  49. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Caching.Abstractions.dll
  50. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Caching.Memory.dll
  51. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll
  52. BIN
      bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll
  53. BIN
      bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll
  54. BIN
      bin/Debug/net8.0/Microsoft.Extensions.DependencyModel.dll
  55. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll
  56. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
  57. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Options.dll
  58. BIN
      bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll
  59. BIN
      bin/Debug/net8.0/Mono.TextTemplating.dll
  60. BIN
      bin/Debug/net8.0/MySqlConnector.dll
  61. BIN
      bin/Debug/net8.0/Pomelo.EntityFrameworkCore.MySql.dll
  62. 973 0
      bin/Debug/net8.0/Recepie.deps.json
  63. BIN
      bin/Debug/net8.0/Recepie.dll
  64. BIN
      bin/Debug/net8.0/Recepie.exe
  65. BIN
      bin/Debug/net8.0/Recepie.pdb
  66. 20 0
      bin/Debug/net8.0/Recepie.runtimeconfig.json
  67. 0 0
      bin/Debug/net8.0/Recepie.staticwebassets.runtime.json
  68. BIN
      bin/Debug/net8.0/System.CodeDom.dll
  69. BIN
      bin/Debug/net8.0/System.Composition.AttributedModel.dll
  70. BIN
      bin/Debug/net8.0/System.Composition.Convention.dll
  71. BIN
      bin/Debug/net8.0/System.Composition.Hosting.dll
  72. BIN
      bin/Debug/net8.0/System.Composition.Runtime.dll
  73. BIN
      bin/Debug/net8.0/System.Composition.TypedParts.dll
  74. BIN
      bin/Debug/net8.0/System.Diagnostics.DiagnosticSource.dll
  75. BIN
      bin/Debug/net8.0/System.IO.Pipelines.dll
  76. BIN
      bin/Debug/net8.0/System.Text.Encodings.Web.dll
  77. BIN
      bin/Debug/net8.0/System.Text.Json.dll
  78. 8 0
      bin/Debug/net8.0/appsettings.Development.json
  79. 9 0
      bin/Debug/net8.0/appsettings.json
  80. BIN
      bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
  81. BIN
      bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll
  82. BIN
      bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll
  83. BIN
      bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll
  84. BIN
      bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.resources.dll
  85. BIN
      bin/Debug/net8.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
  86. BIN
      bin/Debug/net8.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll
  87. BIN
      bin/Debug/net8.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll
  88. BIN
      bin/Debug/net8.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll
  89. BIN
      bin/Debug/net8.0/de/Microsoft.CodeAnalysis.resources.dll
  90. BIN
      bin/Debug/net8.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
  91. BIN
      bin/Debug/net8.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll
  92. BIN
      bin/Debug/net8.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll
  93. BIN
      bin/Debug/net8.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll
  94. BIN
      bin/Debug/net8.0/es/Microsoft.CodeAnalysis.resources.dll
  95. BIN
      bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll
  96. BIN
      bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll
  97. BIN
      bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll
  98. BIN
      bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll
  99. BIN
      bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.resources.dll
  100. BIN
      bin/Debug/net8.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll

+ 106 - 0
.github/copilot-instructions.md

@@ -0,0 +1,106 @@
+<!-- Use this file to provide workspace-specific custom instructions to Copilot. For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file -->
+- [x] Verify that the copilot-instructions.md file in the .github directory is created.
+
+- [x] Clarify Project Requirements
+	<!-- C# ASP.NET Core MVC web application for recipe management with MySQL database connectivity. Requirements clearly specified by user. -->
+
+- [x] Scaffold the Project
+	<!--
+	Ensure that the previous step has been marked as completed.
+	Call project setup tool with projectType parameter.
+	Run scaffolding command to create project files and folders.
+	Use '.' as the working directory.
+	If no appropriate projectType is available, search documentation using available tools.
+	Otherwise, create the project structure manually using available file creation tools.
+	-->
+
+- [x] Customize the Project
+	<!--
+	Verify that all previous steps have been completed successfully and you have marked the step as completed.
+	Develop a plan to modify codebase according to user requirements.
+	Apply modifications using appropriate tools and user-provided references.
+	Skip this step for "Hello World" projects.
+	-->
+
+- [ ] Install Required Extensions
+	<!-- No specific extensions needed for this ASP.NET Core project. -->
+
+- [x] Compile the Project
+	<!--
+	Verify that all previous steps have been completed.
+	Install any missing dependencies.
+	Run diagnostics and resolve any issues.
+	Check for markdown files in project folder for relevant instructions on how to do this.
+	-->
+
+- [x] Create and Run Task
+	<!--
+	Verify that all previous steps have been completed.
+	Check https://code.visualstudio.com/docs/debugtest/tasks to determine if the project needs a task. If so, use the create_and_run_task to create and launch a task based on package.json, README.md, and project structure.
+	Skip this step otherwise.
+	 -->
+
+- [ ] Launch the Project
+	<!--
+	Verify that all previous steps have been completed.
+	Prompt user for debug mode, launch only if confirmed.
+	 -->
+
+- [x] Ensure Documentation is Complete
+	<!--
+	Verify that all previous steps have been completed.
+	Verify that README.md and the copilot-instructions.md file in the .github directory exists and contains current project information.
+	Clean up the copilot-instructions.md file in the .github directory by removing all HTML comments.
+	 -->
+
+<!--
+## Execution Guidelines
+PROGRESS TRACKING:
+- If any tools are available to manage the above todo list, use it to track progress through this checklist.
+- After completing each step, mark it complete and add a summary.
+- Read current todo list status before starting each new step.
+
+COMMUNICATION RULES:
+- Avoid verbose explanations or printing full command outputs.
+- If a step is skipped, state that briefly (e.g. "No extensions needed").
+- Do not explain project structure unless asked.
+- Keep explanations concise and focused.
+
+DEVELOPMENT RULES:
+- Use '.' as the working directory unless user specifies otherwise.
+- Avoid adding media or external links unless explicitly requested.
+- Use placeholders only with a note that they should be replaced.
+- Use VS Code API tool only for VS Code extension projects.
+- Once the project is created, it is already opened in Visual Studio Code—do not suggest commands to open this project in Visual Studio again.
+- If the project setup information has additional rules, follow them strictly.
+
+FOLDER CREATION RULES:
+- Always use the current directory as the project root.
+- If you are running any terminal commands, use the '.' argument to ensure that the current working directory is used ALWAYS.
+- Do not create a new folder unless the user explicitly requests it besides a .vscode folder for a tasks.json file.
+- If any of the scaffolding commands mention that the folder name is not correct, let the user know to create a new folder with the correct name and then reopen it again in vscode.
+
+EXTENSION INSTALLATION RULES:
+- Only install extension specified by the get_project_setup_info tool. DO NOT INSTALL any other extensions.
+
+PROJECT CONTENT RULES:
+- If the user has not specified project details, assume they want a "Hello World" project as a starting point.
+- Avoid adding links of any type (URLs, files, folders, etc.) or integrations that are not explicitly required.
+- Avoid generating images, videos, or any other media files unless explicitly requested.
+- If you need to use any media assets as placeholders, let the user know that these are placeholders and should be replaced with the actual assets later.
+- Ensure all generated components serve a clear purpose within the user's requested workflow.
+- If a feature is assumed but not confirmed, prompt the user for clarification before including it.
+- If you are working on a VS Code extension, use the VS Code API tool with a query to find relevant VS Code API references and samples related to that query.
+
+TASK COMPLETION RULES:
+- Your task is complete when:
+  - Project is successfully scaffolded and compiled without errors
+  - copilot-instructions.md file in the .github directory exists in the project
+  - README.md file exists and is up to date
+  - User is provided with clear instructions to debug/launch the project
+
+Before starting a new task in the above plan, update progress in the plan.
+-->
+- Work through each checklist item systematically.
+- Keep communication concise and focused.
+- Follow development best practices.

+ 21 - 0
.vscode/tasks.json

@@ -0,0 +1,21 @@
+{
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"label": "Run Recipe App",
+			"type": "shell",
+			"command": "dotnet run --project Recepie.sln",
+			"isBackground": true,
+			"problemMatcher": [],
+			"group": "build"
+		},
+		{
+			"label": "Run Recipe App",
+			"type": "shell",
+			"command": "dotnet run",
+			"isBackground": true,
+			"problemMatcher": [],
+			"group": "build"
+		}
+	]
+}

+ 31 - 0
Controllers/HomeController.cs

@@ -0,0 +1,31 @@
+using System.Diagnostics;
+using Microsoft.AspNetCore.Mvc;
+using _.Models;
+
+namespace _.Controllers;
+
+public class HomeController : Controller
+{
+    private readonly ILogger<HomeController> _logger;
+
+    public HomeController(ILogger<HomeController> logger)
+    {
+        _logger = logger;
+    }
+
+    public IActionResult Index()
+    {
+        return View();
+    }
+
+    public IActionResult Privacy()
+    {
+        return View();
+    }
+
+    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+    public IActionResult Error()
+    {
+        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
+    }
+}

+ 362 - 0
Controllers/RecipeController.cs

@@ -0,0 +1,362 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using MySqlConnector;
+using Recepie.Data;
+using Recepie.Models;
+using Recepie.ViewModels;
+
+namespace Recepie.Controllers
+{
+    public class RecipeController : Controller
+    {
+        private readonly RecipeContext _context;
+
+        public RecipeController(RecipeContext context)
+        {
+            _context = context;
+        }
+
+        public async Task<IActionResult> Index(string searchTerm = "", string includeIngredients = "", string excludeIngredients = "", string category = "")
+        {
+            var recipesQuery = _context.Recipes
+                .Include(r => r.RecipeIngredients)
+                    .ThenInclude(ri => ri.Ingredient)
+                .AsQueryable();
+
+            // Search by title or description
+            if (!string.IsNullOrEmpty(searchTerm))
+            {
+                recipesQuery = recipesQuery.Where(r =>
+                    (r.Title != null && r.Title.Contains(searchTerm)) ||
+                    (r.Description != null && r.Description.Contains(searchTerm)));
+            }
+
+            // Include ingredients filter
+            if (!string.IsNullOrEmpty(includeIngredients))
+            {
+                var includeIngredientsList = includeIngredients.Split(',').Select(i => i.Trim().ToLower()).Where(i => !string.IsNullOrEmpty(i)).ToList();
+                if (includeIngredientsList.Any())
+                {
+                    foreach (var ingredient in includeIngredientsList)
+                    {
+                        recipesQuery = recipesQuery.Where(r => r.RecipeIngredients.Any(ri =>
+                            ri.Ingredient != null && ri.Ingredient.Name != null && ri.Ingredient.Name.ToLower().Contains(ingredient)));
+                    }
+                }
+            }
+
+            // Exclude ingredients filter
+            if (!string.IsNullOrEmpty(excludeIngredients))
+            {
+                var excludeIngredientsList = excludeIngredients.Split(',').Select(i => i.Trim().ToLower()).Where(i => !string.IsNullOrEmpty(i)).ToList();
+                if (excludeIngredientsList.Any())
+                {
+                    foreach (var ingredient in excludeIngredientsList)
+                    {
+                        recipesQuery = recipesQuery.Where(r => !r.RecipeIngredients.Any(ri =>
+                            ri.Ingredient != null && ri.Ingredient.Name != null && ri.Ingredient.Name.ToLower().Contains(ingredient)));
+                    }
+                }
+            }
+
+            // Order by title
+            recipesQuery = recipesQuery.OrderBy(r => r.Title);
+
+            var recipes = await recipesQuery.ToListAsync();
+
+            var viewModel = new RecipeIndexViewModel
+            {
+                Recipes = recipes,
+                SearchTerm = searchTerm,
+                IncludeIngredients = includeIngredients,
+                ExcludeIngredients = excludeIngredients,
+                SelectedCategory = "", // Disabled for now
+                Categories = new List<string>() // Empty for now
+            };
+
+            return View(viewModel);
+        }
+
+        public async Task<IActionResult> Details(int id)
+        {
+            var recipe = await _context.Recipes
+                .Include(r => r.RecipeIngredients)
+                    .ThenInclude(ri => ri.Ingredient)
+                .Include(r => r.RecipeSteps)
+                .FirstOrDefaultAsync(r => r.Id == id);
+
+            if (recipe == null)
+            {
+                return NotFound();
+            }
+
+            return View(recipe);
+        }
+
+        // Action to serve recipe images from BLOB data
+        public async Task<IActionResult> GetImage(int recipeId)
+        {
+            try
+            {
+                var connection = _context.Database.GetDbConnection();
+                await connection.OpenAsync();
+                
+                using var command = connection.CreateCommand();
+                command.CommandText = "SELECT image FROM recepieImage WHERE recepieId = @recipeId";
+                command.Parameters.Add(new MySqlConnector.MySqlParameter("@recipeId", recipeId));
+                
+                var result = await command.ExecuteScalarAsync();
+                await connection.CloseAsync();
+                
+                if (result == null || result == DBNull.Value)
+                {
+                    return NotFound();
+                }
+                
+                var imageData = (byte[])result;
+                return File(imageData, "image/jpeg");
+            }
+            catch
+            {
+                return NotFound();
+            }
+        }
+
+        // Check if recipe has image without loading BLOB data
+        public async Task<IActionResult> HasImage(int recipeId)
+        {
+            try
+            {
+                var connection = _context.Database.GetDbConnection();
+                await connection.OpenAsync();
+                
+                using var command = connection.CreateCommand();
+                command.CommandText = "SELECT COUNT(*) FROM recepieImage WHERE recepieId = @recipeId AND image IS NOT NULL";
+                command.Parameters.Add(new MySqlConnector.MySqlParameter("@recipeId", recipeId));
+                
+                var count = await command.ExecuteScalarAsync();
+                await connection.CloseAsync();
+                
+                var hasImage = Convert.ToInt32(count) > 0;
+                return Json(hasImage);
+            }
+            catch
+            {
+                return Json(false);
+            }
+        }
+
+        // Action to serve recipe images from BLOB data - Temporarily disabled
+        /*
+        public async Task<IActionResult> GetImage(int recipeId, int imageId = 0)
+        {
+            RecipeImage? recipeImage;
+            
+            if (imageId > 0)
+            {
+                // Get specific image by ID
+                recipeImage = await _context.RecipeImages
+                    .FirstOrDefaultAsync(ri => ri.Id == imageId && ri.RecipeId == recipeId);
+            }
+            else
+            {
+                // Get first image for the recipe
+                recipeImage = await _context.RecipeImages
+                    .FirstOrDefaultAsync(ri => ri.RecipeId == recipeId);
+            }
+
+            if (recipeImage?.ImageData == null)
+            {
+                return NotFound();
+            }
+
+            // Determine content type (default to JPEG if not specified)
+            string contentType = !string.IsNullOrEmpty(recipeImage.ContentType) 
+                ? recipeImage.ContentType 
+                : "image/jpeg";
+
+            return File(recipeImage.ImageData, contentType);
+        }
+        */
+
+        public IActionResult Create()
+        {
+            return View();
+        }
+
+        [HttpPost]
+        [ValidateAntiForgeryToken]
+        public async Task<IActionResult> Create([Bind("Id,Title,Description,Difficulty,Url,Time")] Recipe recipe)
+        {
+            if (ModelState.IsValid)
+            {
+                _context.Add(recipe);
+                await _context.SaveChangesAsync();
+                return RedirectToAction(nameof(Index));
+            }
+            return View(recipe);
+        }
+
+        public async Task<IActionResult> Edit(int id)
+        {
+            var recipe = await _context.Recipes.FindAsync(id);
+            if (recipe == null)
+            {
+                return NotFound();
+            }
+            return View(recipe);
+        }
+
+        [HttpPost]
+        [ValidateAntiForgeryToken]
+        public async Task<IActionResult> Edit(int id, [Bind("Id,Title,Description,Difficulty,Url,Time")] Recipe recipe)
+        {
+            if (id != recipe.Id)
+            {
+                return NotFound();
+            }
+
+            if (ModelState.IsValid)
+            {
+                try
+                {
+                    _context.Update(recipe);
+                    await _context.SaveChangesAsync();
+                }
+                catch (DbUpdateConcurrencyException)
+                {
+                    if (!RecipeExists(recipe.Id))
+                    {
+                        return NotFound();
+                    }
+                    else
+                    {
+                        throw;
+                    }
+                }
+                return RedirectToAction(nameof(Index));
+            }
+            return View(recipe);
+        }
+
+        public async Task<IActionResult> Delete(int id)
+        {
+            var recipe = await _context.Recipes.FindAsync(id);
+            if (recipe == null)
+            {
+                return NotFound();
+            }
+
+            return View(recipe);
+        }
+
+        [HttpPost, ActionName("Delete")]
+        [ValidateAntiForgeryToken]
+        public async Task<IActionResult> DeleteConfirmed(int id)
+        {
+            var recipe = await _context.Recipes.FindAsync(id);
+            if (recipe != null)
+            {
+                _context.Recipes.Remove(recipe);
+            }
+
+            await _context.SaveChangesAsync();
+            return RedirectToAction(nameof(Index));
+        }
+
+        private bool RecipeExists(int id)
+        {
+            return _context.Recipes.Any(e => e.Id == id);
+        }
+
+        // Simplified API endpoint for testing
+        [HttpGet]
+        public async Task<IActionResult> Api()
+        {
+            var recipes = await _context.Recipes.Take(10).ToListAsync();
+            return Json(recipes);
+        }
+
+        // Simple test page
+        public IActionResult SimpleTest()
+        {
+            return View();
+        }
+
+        // Database inspection
+        public async Task<IActionResult> InspectDatabase()
+        {
+            try
+            {
+                // Try to query the information_schema to get table names
+                var tablesQuery = @"
+                    SELECT TABLE_NAME 
+                    FROM information_schema.TABLES 
+                    WHERE TABLE_SCHEMA = 'recept'";
+                
+                var connection = _context.Database.GetDbConnection();
+                await connection.OpenAsync();
+                
+                using var command = connection.CreateCommand();
+                command.CommandText = tablesQuery;
+                
+                var tables = new List<string>();
+                using var reader = await command.ExecuteReaderAsync();
+                while (await reader.ReadAsync())
+                {
+                    tables.Add(reader.GetString(0));
+                }
+                await reader.CloseAsync();
+                
+                ViewBag.Tables = tables;
+                
+                // Check if recepieImage table exists
+                var imageTableExists = tables.Any(t => t.ToLower().Contains("image"));
+                ViewBag.ImageTableExists = imageTableExists;
+                
+                if (imageTableExists)
+                {
+                    var imageTableName = tables.FirstOrDefault(t => t.ToLower().Contains("image"));
+                    ViewBag.ImageTableName = imageTableName;
+                    
+                    // Get table structure
+                    try
+                    {
+                        command.CommandText = $"DESCRIBE `{imageTableName}`";
+                        using var structureReader = await command.ExecuteReaderAsync();
+                        
+                        var columns = new List<string>();
+                        while (await structureReader.ReadAsync())
+                        {
+                            var field = structureReader.GetString(0);
+                            var type = structureReader.GetString(1);
+                            var isNull = structureReader.GetString(2);
+                            var key = structureReader.GetString(3);
+                            columns.Add($"{field} ({type}) {(key == "PRI" ? "PRIMARY KEY" : "")} {(isNull == "YES" ? "NULL" : "NOT NULL")}");
+                        }
+                        await structureReader.CloseAsync();
+                        ViewBag.ImageTableColumns = columns;
+                        
+                        // Get sample data count
+                        command.CommandText = $"SELECT COUNT(*) FROM `{imageTableName}`";
+                        var count = await command.ExecuteScalarAsync();
+                        ViewBag.ImageRecordCount = count;
+                        
+                    }
+                    catch (Exception ex)
+                    {
+                        ViewBag.ImageTableError = ex.Message;
+                    }
+                }
+                
+                await connection.CloseAsync();
+                return View();
+            }
+            catch (Exception ex)
+            {
+                ViewBag.Error = ex.Message;
+                return View();
+            }
+        }
+    }
+}

+ 100 - 0
Data/RecipeContext.cs

@@ -0,0 +1,100 @@
+using Microsoft.EntityFrameworkCore;
+using Recepie.Models;
+
+namespace Recepie.Data
+{
+    public class RecipeContext : DbContext
+    {
+        public RecipeContext(DbContextOptions<RecipeContext> options) : base(options)
+        {
+        }
+
+        public DbSet<Recipe> Recipes { get; set; }
+        public DbSet<Ingredient> Ingredients { get; set; }
+        public DbSet<RecipeIngredientLink> RecipeIngredientLinks { get; set; }
+        public DbSet<RecipeStep> RecipeSteps { get; set; }
+        // public DbSet<RecipeImage> RecipeImages { get; set; }  // Temporarily disabled for main page performance
+
+        protected override void OnModelCreating(ModelBuilder modelBuilder)
+        {
+            base.OnModelCreating(modelBuilder);
+
+            modelBuilder.Entity<Recipe>(entity =>
+            {
+                // Map to existing lowercase table name
+                entity.ToTable("recepie");
+
+                entity.HasKey(e => e.Id);
+                entity.Property(e => e.Id).HasColumnName("id");
+
+                // Map our model properties to your database columns
+                entity.Property(e => e.Title).HasColumnName("name").IsRequired();
+                entity.Property(e => e.Description).HasColumnName("description");
+                entity.Property(e => e.Difficulty).HasColumnName("difficulty");
+                entity.Property(e => e.Url).HasColumnName("url");
+                entity.Property(e => e.Time).HasColumnName("time");
+
+                // Index for better search performance
+                entity.HasIndex(e => e.Title);
+            });
+
+            modelBuilder.Entity<Ingredient>(entity =>
+            {
+                entity.ToTable("ingredient");
+                entity.HasKey(e => e.Id);
+                entity.Property(e => e.Id).HasColumnName("id");
+                entity.Property(e => e.Name).HasColumnName("name");
+            });
+
+            modelBuilder.Entity<RecipeIngredientLink>(entity =>
+            {
+                entity.ToTable("recepieIngredientLink");
+                entity.HasKey(e => new { e.RecipeId, e.IngredientId });
+                entity.Property(e => e.RecipeId).HasColumnName("recepieId");
+                entity.Property(e => e.IngredientId).HasColumnName("ingredientId");
+                entity.Property(e => e.Amount).HasColumnName("amount");
+                entity.Property(e => e.Measurement).HasColumnName("measurement");
+
+                // Configure relationships
+                entity.HasOne(e => e.Recipe)
+                    .WithMany(r => r.RecipeIngredients)
+                    .HasForeignKey(e => e.RecipeId);
+
+                entity.HasOne(e => e.Ingredient)
+                    .WithMany()
+                    .HasForeignKey(e => e.IngredientId);
+            });
+
+            modelBuilder.Entity<RecipeStep>(entity =>
+            {
+                entity.ToTable("recepieSteps");
+                entity.HasKey(e => e.Id);
+                entity.Property(e => e.Id).HasColumnName("id");
+                entity.Property(e => e.RecipeId).HasColumnName("recepieId");
+                entity.Property(e => e.StepNumber).HasColumnName("stepNumber");
+                entity.Property(e => e.Text).HasColumnName("text");
+
+                // Configure relationship
+                entity.HasOne(e => e.Recipe)
+                    .WithMany(r => r.RecipeSteps)
+                    .HasForeignKey(e => e.RecipeId);
+            });
+
+            // Temporarily disabled RecipeImage configuration for performance
+            /*
+            modelBuilder.Entity<RecipeImage>(entity =>
+            {
+                entity.ToTable("recepieImage");
+                entity.HasKey(e => e.RecipeId);
+                entity.Property(e => e.RecipeId).HasColumnName("recepieId");
+                entity.Property(e => e.ImageData).HasColumnName("image");
+
+                // Configure relationship
+                entity.HasOne(e => e.Recipe)
+                    .WithOne(r => r.RecipeImage)
+                    .HasForeignKey<RecipeImage>(e => e.RecipeId);
+            });
+            */
+        }
+    }
+}

+ 8 - 0
Models/ErrorViewModel.cs

@@ -0,0 +1,8 @@
+namespace _.Models;
+
+public class ErrorViewModel
+{
+    public string? RequestId { get; set; }
+
+    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+}

+ 12 - 0
Models/Ingredient.cs

@@ -0,0 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Recepie.Models
+{
+    public class Ingredient
+    {
+        [Key]
+        public int Id { get; set; }
+
+        public string? Name { get; set; }
+    }
+}

+ 34 - 0
Models/Recipe.cs

@@ -0,0 +1,34 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Recepie.Models
+{
+    public class Recipe
+    {
+        [Key]
+        public int Id { get; set; }
+
+        [Required]
+        [StringLength(200)]
+        public string Title { get; set; } = string.Empty;
+
+        [StringLength(1000)]
+        public string? Description { get; set; }
+
+        [StringLength(50)]
+        public string? Difficulty { get; set; }
+
+        // Properties that exist in your database - made nullable to handle NULL values
+        public string? Url { get; set; }
+        public string? Time { get; set; }
+
+        // Navigation properties for ingredients, steps, and images
+        public virtual ICollection<RecipeIngredientLink> RecipeIngredients { get; set; } = new List<RecipeIngredientLink>();
+        public virtual ICollection<RecipeStep> RecipeSteps { get; set; } = new List<RecipeStep>();
+        // public virtual RecipeImage? RecipeImage { get; set; }  // Temporarily disabled for main page performance
+
+        // Computed property to get ingredient names
+        [NotMapped]
+        public List<string> IngredientNames => RecipeIngredients?.Select(ri => ri.Ingredient?.Name ?? "").Where(name => !string.IsNullOrEmpty(name)).ToList() ?? new List<string>();
+    }
+}

+ 17 - 0
Models/RecipeImage.cs

@@ -0,0 +1,17 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Recepie.Models
+{
+    public class RecipeImage
+    {
+        // No ID column - use recepieId as key
+        [Key]
+        public int RecipeId { get; set; }
+        
+        public byte[]? ImageData { get; set; }
+        
+        // Navigation property
+        public Recipe? Recipe { get; set; }
+    }
+}

+ 18 - 0
Models/RecipeIngredientLink.cs

@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Recepie.Models
+{
+    public class RecipeIngredientLink
+    {
+        public int RecipeId { get; set; }
+        public int IngredientId { get; set; }
+
+        // Amount and measurement information
+        public string? Amount { get; set; }
+        public string? Measurement { get; set; }
+
+        // Navigation properties
+        public Recipe? Recipe { get; set; }
+        public Ingredient? Ingredient { get; set; }
+    }
+}

+ 17 - 0
Models/RecipeStep.cs

@@ -0,0 +1,17 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Recepie.Models
+{
+    public class RecipeStep
+    {
+        [Key]
+        public int Id { get; set; }
+
+        public int RecipeId { get; set; }
+        public int StepNumber { get; set; }
+        public string Text { get; set; } = string.Empty;
+
+        // Navigation property
+        public Recipe? Recipe { get; set; }
+    }
+}

+ 35 - 0
Program.cs

@@ -0,0 +1,35 @@
+using Microsoft.EntityFrameworkCore;
+using Recepie.Data;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddControllersWithViews();
+
+// Configure MySQL database connection
+var connectionString = "Server=nordh.xyz;Port=3306;Database=recept;User=recepieUser;Password=v.FV-ssZPzVyev28;";
+builder.Services.AddDbContext<RecipeContext>(options =>
+    options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (!app.Environment.IsDevelopment())
+{
+    app.UseExceptionHandler("/Home/Error");
+    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+    app.UseHsts();
+}
+
+app.UseHttpsRedirection();
+app.UseStaticFiles();
+
+app.UseRouting();
+
+app.UseAuthorization();
+
+app.MapControllerRoute(
+    name: "default",
+    pattern: "{controller=Recipe}/{action=Index}/{id?}");
+
+app.Run();

+ 38 - 0
Properties/launchSettings.json

@@ -0,0 +1,38 @@
+{
+  "$schema": "http://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:33918",
+      "sslPort": 44307
+    }
+  },
+  "profiles": {
+    "http": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "applicationUrl": "http://localhost:5104",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "https": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:7012;http://localhost:5104",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}

+ 135 - 0
README.md

@@ -0,0 +1,135 @@
+# Recipe Manager
+
+A C# ASP.NET Core MVC web application for managing your personal recipe collection with advanced search and filtering capabilities.
+
+## Features
+
+- **Recipe Management**: Add, edit, view, and delete recipes
+- **Advanced Search**: Search recipes by title, description, and ingredients
+- **Smart Filtering**: 
+  - Filter by category
+  - Include specific ingredients (must-have)
+  - Exclude unwanted ingredients (allergens, dietary restrictions)
+- **Responsive Design**: Works on desktop, tablet, and mobile devices
+- **Interactive UI**: 
+  - Ingredient checklist in recipe details
+  - Real-time search and filtering
+  - Recipe cards with hover effects
+
+## Database Configuration
+
+The application connects to a MySQL database with the following configuration:
+- **Server**: nordh.xyz:3306
+- **Database**: recept
+- **Username**: recepieUser
+- **Password**: v.FV-ssZPzVyev28
+
+## Getting Started
+
+### Prerequisites
+
+- .NET 8.0 SDK
+- Access to the MySQL database (credentials provided above)
+
+### Running the Application
+
+1. Clone or download this project
+2. Open the project in Visual Studio Code
+3. Open a terminal and navigate to the project directory
+4. Run the application:
+   ```bash
+   dotnet run
+   ```
+5. Open your web browser and navigate to `http://localhost:5104`
+
+### Building the Application
+
+```bash
+dotnet build Recepie.sln
+```
+
+## Project Structure
+
+```
+Recepie/
+├── Controllers/
+│   └── RecipeController.cs      # Main controller with search/filter logic
+├── Data/
+│   └── RecipeContext.cs         # Entity Framework DbContext
+├── Models/
+│   └── Recipe.cs                # Recipe entity model
+├── ViewModels/
+│   └── RecipeIndexViewModel.cs  # ViewModel for index page
+├── Views/
+│   ├── Recipe/
+│   │   ├── Index.cshtml         # Main recipe listing with search/filter
+│   │   ├── Details.cshtml       # Recipe details view
+│   │   ├── Create.cshtml        # Add new recipe form
+│   │   ├── Edit.cshtml          # Edit recipe form
+│   │   └── Delete.cshtml        # Delete confirmation
+│   └── Shared/
+│       └── _Layout.cshtml       # Main layout template
+└── wwwroot/
+    └── css/
+        └── site.css             # Custom styling
+```
+
+## Usage
+
+### Adding Recipes
+
+1. Click "Add New Recipe" button
+2. Fill in the recipe details:
+   - Title and description
+   - Category and difficulty level
+   - Preparation and cooking times
+   - Number of servings
+   - Ingredients (comma-separated)
+   - Step-by-step instructions
+3. Click "Save Recipe"
+
+### Searching and Filtering
+
+Use the left sidebar to:
+
+- **Search**: Enter keywords to search in titles, descriptions, and ingredients
+- **Category Filter**: Select a specific recipe category
+- **Include Ingredients**: Enter ingredients that must be present (comma-separated)
+- **Exclude Ingredients**: Enter ingredients to avoid (comma-separated)
+
+### Example Searches
+
+- Find all recipes with "chicken": Enter "chicken" in the search box
+- Find recipes you can make with eggs and flour: Enter "eggs, flour" in "Must Have Ingredients"
+- Find recipes without nuts: Enter "nuts" in "Must NOT Have Ingredients"
+- Combine filters: Search for "pasta" with "tomato" included and "meat" excluded
+
+## Technology Stack
+
+- **Backend**: ASP.NET Core 8.0 MVC
+- **Database**: MySQL with Entity Framework Core
+- **Frontend**: Bootstrap 5, Font Awesome icons, jQuery
+- **Styling**: Custom CSS with responsive design
+
+## Database Schema
+
+The Recipe entity includes:
+- **Id**: Primary key
+- **Title**: Recipe name (required)
+- **Description**: Brief description
+- **Ingredients**: Comma-separated list (required)
+- **Instructions**: Step-by-step cooking instructions
+- **Category**: Recipe category (e.g., "Main Course", "Dessert")
+- **Difficulty**: Easy, Medium, or Hard
+- **PreparationTimeMinutes**: Prep time
+- **CookingTimeMinutes**: Cooking time
+- **Servings**: Number of servings
+- **CreatedAt/UpdatedAt**: Timestamps
+
+## Contributing
+
+This is a personal recipe management application. Feel free to customize it for your needs!
+
+## License
+
+This project is for personal use.

+ 20 - 0
Recepie.csproj

@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <RootNamespace>Recepie</RootNamespace>
+    <AssemblyName>Recepie</AssemblyName>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
+  </ItemGroup>
+
+</Project>

+ 24 - 0
Recepie.sln

@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Recepie", "Recepie.csproj", "{FEA91663-7214-B722-A16E-B69FFDC74FA0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{FEA91663-7214-B722-A16E-B69FFDC74FA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{FEA91663-7214-B722-A16E-B69FFDC74FA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{FEA91663-7214-B722-A16E-B69FFDC74FA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{FEA91663-7214-B722-A16E-B69FFDC74FA0}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {C84D20FB-D3FF-424A-9220-2E2B9255469B}
+	EndGlobalSection
+EndGlobal

+ 20 - 0
ViewModels/RecipeIndexViewModel.cs

@@ -0,0 +1,20 @@
+using Recepie.Models;
+
+namespace Recepie.ViewModels
+{
+    public class RecipeIndexViewModel
+    {
+        public List<Recipe> Recipes { get; set; } = new List<Recipe>();
+        public string SearchTerm { get; set; } = string.Empty;
+        public string IncludeIngredients { get; set; } = string.Empty;
+        public string ExcludeIngredients { get; set; } = string.Empty;
+        public string SelectedCategory { get; set; } = string.Empty;
+        public List<string> Categories { get; set; } = new List<string>();
+
+        public int TotalRecipes => Recipes.Count;
+        public bool HasFilters => !string.IsNullOrEmpty(SearchTerm) ||
+                                  !string.IsNullOrEmpty(IncludeIngredients) ||
+                                  !string.IsNullOrEmpty(ExcludeIngredients) ||
+                                  !string.IsNullOrEmpty(SelectedCategory);
+    }
+}

+ 8 - 0
Views/Home/Index.cshtml

@@ -0,0 +1,8 @@
+@{
+    ViewData["Title"] = "Home Page";
+}
+
+<div class="text-center">
+    <h1 class="display-4">Welcome</h1>
+    <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+</div>

+ 6 - 0
Views/Home/Privacy.cshtml

@@ -0,0 +1,6 @@
+@{
+    ViewData["Title"] = "Privacy Policy";
+}
+<h1>@ViewData["Title"]</h1>
+
+<p>Use this page to detail your site's privacy policy.</p>

+ 68 - 0
Views/Recipe/Create.cshtml

@@ -0,0 +1,68 @@
+@model Recepie.Models.Recipe
+
+@{
+    ViewData["Title"] = "Create Recipe";
+}
+
+<div class="container mt-4">
+    <div class="row">
+        <div class="col-md-8 offset-md-2">
+            <div class="card">
+                <div class="card-header">
+                    <h2>Create New Recipe</h2>
+                </div>
+                <div class="card-body">
+                    <form asp-action="Create">
+                        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
+
+                        <div class="mb-3">
+                            <label asp-for="Title" class="form-label"></label>
+                            <input asp-for="Title" class="form-control" />
+                            <span asp-validation-for="Title" class="text-danger"></span>
+                        </div>
+
+                        <div class="mb-3">
+                            <label asp-for="Description" class="form-label"></label>
+                            <textarea asp-for="Description" class="form-control" rows="4"></textarea>
+                            <span asp-validation-for="Description" class="text-danger"></span>
+                        </div>
+
+                        <div class="mb-3">
+                            <label asp-for="Difficulty" class="form-label"></label>
+                            <select asp-for="Difficulty" class="form-select">
+                                <option value="">Select difficulty</option>
+                                <option value="Easy">Easy</option>
+                                <option value="Medium">Medium</option>
+                                <option value="Hard">Hard</option>
+                            </select>
+                            <span asp-validation-for="Difficulty" class="text-danger"></span>
+                        </div>
+
+                        <div class="mb-3">
+                            <label asp-for="Time" class="form-label"></label>
+                            <input asp-for="Time" class="form-control" placeholder="e.g., 30 minutes" />
+                            <span asp-validation-for="Time" class="text-danger"></span>
+                        </div>
+
+                        <div class="mb-3">
+                            <label asp-for="Url" class="form-label"></label>
+                            <input asp-for="Url" class="form-control" type="url" placeholder="https://..." />
+                            <span asp-validation-for="Url" class="text-danger"></span>
+                        </div>
+
+                        <div class="d-grid gap-2 d-md-flex justify-content-md-end">
+                            <a href="@Url.Action("Index")" class="btn btn-secondary">Cancel</a>
+                            <button type="submit" class="btn btn-primary">Create</button>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+@section Scripts {
+    @{
+        await Html.RenderPartialAsync("_ValidationScriptsPartial");
+    }
+}

+ 51 - 0
Views/Recipe/Delete.cshtml

@@ -0,0 +1,51 @@
+@model Recepie.Models.Recipe
+
+@{
+    ViewData["Title"] = "Delete Recipe";
+}
+
+<div class="container mt-4">
+    <div class="row">
+        <div class="col-md-8 offset-md-2">
+            <div class="card border-danger">
+                <div class="card-header bg-danger text-white">
+                    <h2>Delete Recipe</h2>
+                </div>
+                <div class="card-body">
+                    <div class="alert alert-warning">
+                        <i class="fas fa-exclamation-triangle"></i>
+                        Are you sure you want to delete this recipe? This action cannot be undone.
+                    </div>
+                    
+                    <h3>@Model.Title</h3>
+                    <p class="lead">@Model.Description</p>
+                    
+                    @if (!string.IsNullOrEmpty(Model.Difficulty))
+                    {
+                        <p><strong>Difficulty:</strong> <span class="badge bg-info">@Model.Difficulty</span></p>
+                    }
+
+                    @if (!string.IsNullOrEmpty(Model.Time))
+                    {
+                        <p><strong>Time:</strong> @Model.Time</p>
+                    }
+
+                    @if (!string.IsNullOrEmpty(Model.Url))
+                    {
+                        <p><strong>Recipe URL:</strong> <a href="@Model.Url" target="_blank">@Model.Url</a></p>
+                    }
+                    
+                    <form asp-action="Delete" method="post" class="d-inline">
+                        <input type="hidden" asp-for="Id" />
+                        <div class="d-grid gap-2 d-md-flex justify-content-md-end mt-4">
+                            <a href="@Url.Action("Details", new { id = Model.Id })" class="btn btn-secondary">Cancel</a>
+                            <button type="submit" class="btn btn-danger">
+                                <i class="fas fa-trash"></i> Delete Recipe
+                            </button>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 188 - 0
Views/Recipe/Details.cshtml

@@ -0,0 +1,188 @@
+@model Recepie.Models.Recipe
+
+@{
+    ViewData["Title"] = "Recipe Details";
+}
+
+<style>
+    .step-content {
+        line-height: 1.6;
+        margin-bottom: 0.5rem;
+    }
+
+    .ingredient-item {
+        padding: 0.5rem;
+        background-color: #f8f9fa;
+        border-radius: 0.25rem;
+        margin-bottom: 0.5rem;
+    }
+
+    .ingredient-amount {
+        font-weight: bold;
+        color: #007bff;
+    }
+</style>
+
+<div class="container mt-4">
+    <div class="row">
+        <div class="col-md-8">
+            <div class="card">
+                <div class="card-header">
+                    <h2>@Model.Title</h2>
+                </div>
+                <div class="card-body">
+                    <p class="lead">@Model.Description</p>
+
+                    @* Temporarily disabled for main page performance
+                    @if (Model.RecipeImage?.ImageData != null)
+                    {
+                        <div class="mb-4">
+                            <h5><i class="fas fa-camera"></i> Recipe Image</h5>
+                            <div class="text-center">
+                                <img src="@Url.Action("GetImage", "Recipe", new { recipeId = Model.Id })" 
+                                     class="img-fluid rounded shadow" 
+                                     alt="@Model.Title" 
+                                     style="max-height: 400px; object-fit: cover;" />
+                            </div>
+                        </div>
+                    }
+                    *@
+
+                    <div class="mb-4">
+                        <h5><i class="fas fa-camera"></i> Recipe Image</h5>
+                        <div class="text-center">
+                            <img src="@Url.Action("GetImage", "Recipe", new { recipeId = Model.Id })" 
+                                 class="img-fluid rounded shadow" 
+                                 alt="@Model.Title" 
+                                 style="max-height: 400px; object-fit: cover;" 
+                                 onerror="this.style.display='none'" />
+                        </div>
+                    </div>
+
+                    @if (!string.IsNullOrEmpty(Model.Difficulty))
+                    {
+                        <div class="mb-3">
+                            <strong>Difficulty:</strong> <span class="badge bg-info">@Model.Difficulty</span>
+                        </div>
+                    }
+
+                    @if (!string.IsNullOrEmpty(Model.Time))
+                    {
+                        <div class="mb-3">
+                            <strong>Time:</strong> @Model.Time
+                        </div>
+                    }
+
+                    @if (Model.RecipeIngredients.Any())
+                    {
+                        <div class="mb-4">
+                            <h5><i class="fas fa-list"></i> Ingredients</h5>
+                            <div class="card">
+                                <div class="card-body">
+                                    <ul class="list-unstyled mb-0">
+                                        @foreach (var recipeIngredient in Model.RecipeIngredients.OrderBy(ri =>
+                                                                            ri.Ingredient.Name))
+                                        {
+                                            <li class="ingredient-item d-flex align-items-center">
+                                                <i class="fas fa-check text-success me-2"></i>
+                                                <span class="ingredient-amount me-2">
+                                                    @if (!string.IsNullOrEmpty(recipeIngredient.Amount))
+                                                    {
+                                                        @recipeIngredient.Amount
+                                                    }
+                                                    @if (!string.IsNullOrEmpty(recipeIngredient.Measurement))
+                                                    {
+                                                        <text> @recipeIngredient.Measurement</text>
+                                                    }
+                                                </span>
+                                                <span>@recipeIngredient.Ingredient?.Name</span>
+                                            </li>
+                                        }
+                                    </ul>
+                                </div>
+                            </div>
+                        </div>
+                    }
+
+                    @if (Model.RecipeSteps.Any())
+                    {
+                        <div class="mb-4">
+                            <h5><i class="fas fa-clipboard-list"></i> Instructions</h5>
+                            <div class="card">
+                                <div class="card-body">
+                                    <ol class="mb-0">
+                                        @foreach (var step in Model.RecipeSteps.OrderBy(s => s.StepNumber))
+                                        {
+                                            <li class="mb-3">
+                                                <div class="step-content">
+                                                    @step.Text
+                                                </div>
+                                            </li>
+                                        }
+                                    </ol>
+                                </div>
+                            </div>
+                        </div>
+                    }
+
+                    @if (!string.IsNullOrEmpty(Model.Url))
+                    {
+                        <div class="mb-3">
+                            <strong>Recipe URL:</strong>
+                            <a href="@Model.Url" target="_blank" class="btn btn-outline-primary btn-sm">
+                                <i class="fas fa-external-link-alt"></i> View Original Recipe
+                            </a>
+                        </div>
+                    }
+                </div>
+            </div>
+        </div>
+
+        <div class="col-md-4">
+            <div class="card">
+                <div class="card-header">
+                    <h5>Actions</h5>
+                </div>
+                <div class="card-body">
+                    <div class="d-grid gap-2">
+                        @if (!string.IsNullOrEmpty(Model.Url))
+                        {
+                            <a href="@Model.Url" target="_blank" class="btn btn-success">
+                                <i class="fas fa-external-link-alt"></i> View Recipe
+                            </a>
+                        }
+                        <a href="@Url.Action("Edit", new { id = Model.Id })" class="btn btn-warning">
+                            <i class="fas fa-edit"></i> Edit Recipe
+                        </a>
+                        <a href="@Url.Action("Delete", new { id = Model.Id })" class="btn btn-danger">
+                            <i class="fas fa-trash"></i> Delete Recipe
+                        </a>
+                        <a href="@Url.Action("Index")" class="btn btn-secondary">
+                            <i class="fas fa-arrow-left"></i> Back to List
+                        </a>
+                    </div>
+                </div>
+            </div>
+
+            @if (Model.IngredientNames.Any())
+            {
+                <div class="card mt-3">
+                    <div class="card-header">
+                        <h6>Quick Filter by Ingredients</h6>
+                    </div>
+                    <div class="card-body">
+                        <div class="d-grid gap-1">
+                            @foreach (var ingredient in Model.IngredientNames.Take(5))
+                            {
+                                <a href="@Url.Action("Index", new { includeIngredients = ingredient })"
+                                    class="btn btn-outline-primary btn-sm">
+                                    Find recipes with @ingredient
+                                </a>
+                            }
+                        </div>
+                    </div>
+                </div>
+            }
+        </div>
+    </div>
+</div>

+ 67 - 0
Views/Recipe/Edit.cshtml

@@ -0,0 +1,67 @@
+@model Recepie.Models.Recipe
+
+@{
+    ViewData["Title"] = "Edit Recipe";
+}
+
+<div class="container mt-4">
+    <div class="row">
+        <div class="col-md-8 offset-md-2">
+            <div class="card">
+                <div class="card-header">
+                    <h2>Edit Recipe</h2>
+                </div>
+                <div class="card-body">
+                    <form asp-action="Edit">
+                        <input type="hidden" asp-for="Id" />
+                        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
+                        
+                        <div class="mb-3">
+                            <label asp-for="Title" class="form-label"></label>
+                            <input asp-for="Title" class="form-control" />
+                            <span asp-validation-for="Title" class="text-danger"></span>
+                        </div>
+                        
+                        <div class="mb-3">
+                            <label asp-for="Description" class="form-label"></label>
+                            <textarea asp-for="Description" class="form-control" rows="4"></textarea>
+                            <span asp-validation-for="Description" class="text-danger"></span>
+                        </div>
+                        
+                        <div class="mb-3">
+                            <label asp-for="Difficulty" class="form-label"></label>
+                            <select asp-for="Difficulty" class="form-select">
+                                <option value="">Select difficulty</option>
+                                <option value="Easy">Easy</option>
+                                <option value="Medium">Medium</option>
+                                <option value="Hard">Hard</option>
+                            </select>
+                            <span asp-validation-for="Difficulty" class="text-danger"></span>
+                        </div>
+                        
+                        <div class="mb-3">
+                            <label asp-for="Time" class="form-label"></label>
+                            <input asp-for="Time" class="form-control" placeholder="e.g., 30 minutes" />
+                            <span asp-validation-for="Time" class="text-danger"></span>
+                        </div>
+                        
+                        <div class="mb-3">
+                            <label asp-for="Url" class="form-label"></label>
+                            <input asp-for="Url" class="form-control" type="url" placeholder="https://..." />
+                            <span asp-validation-for="Url" class="text-danger"></span>
+                        </div>
+                        
+                        <div class="d-grid gap-2 d-md-flex justify-content-md-end">
+                            <a href="@Url.Action("Details", new { id = Model.Id })" class="btn btn-secondary">Cancel</a>
+                            <button type="submit" class="btn btn-primary">Save Changes</button>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+@section Scripts {
+    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
+}

+ 170 - 0
Views/Recipe/Index.cshtml

@@ -0,0 +1,170 @@
+@model Recepie.ViewModels.RecipeIndexViewModel
+
+@{
+    ViewData["Title"] = "Recipe Search";
+}
+
+<div class="container-fluid mt-4">
+    <div class="row">
+        <div class="col-md-3">
+            <!-- Search Panel -->
+            <div class="card">
+                <div class="card-header">
+                    <h5 class="mb-0">
+                        <i class="fas fa-search"></i> Search Recipes
+                    </h5>
+                </div>
+                <div class="card-body">
+                    <form method="get" asp-action="Index">
+                        <!-- Search Term -->
+                        <div class="mb-3">
+                            <label for="searchTerm" class="form-label">Search</label>
+                            <input type="text" class="form-control" id="searchTerm" name="searchTerm"
+                                value="@Model.SearchTerm" placeholder="Search title or description...">
+                        </div>
+
+                        <!-- Include Ingredients -->
+                        <div class="mb-3">
+                            <label for="includeIngredients" class="form-label">
+                                <i class="fas fa-plus text-success"></i> Must Have Ingredients
+                            </label>
+                            <input type="text" class="form-control" id="includeIngredients" name="includeIngredients"
+                                value="@Model.IncludeIngredients" placeholder="chicken, tomato, onion...">
+                            <div class="form-text">Comma-separated list</div>
+                        </div>
+
+                        <!-- Exclude Ingredients -->
+                        <div class="mb-3">
+                            <label for="excludeIngredients" class="form-label">
+                                <i class="fas fa-minus text-danger"></i> Exclude Ingredients
+                            </label>
+                            <input type="text" class="form-control" id="excludeIngredients" name="excludeIngredients"
+                                value="@Model.ExcludeIngredients" placeholder="nuts, dairy, gluten...">
+                            <div class="form-text">Comma-separated list</div>
+                        </div>
+
+                        <button type="submit" class="btn btn-primary w-100">
+                            <i class="fas fa-search"></i> Search & Filter
+                        </button>
+
+                        @if (!string.IsNullOrEmpty(Model.SearchTerm) || !string.IsNullOrEmpty(Model.IncludeIngredients)
+                                                || !string.IsNullOrEmpty(Model.ExcludeIngredients))
+                        {
+                            <a href="@Url.Action("Index")" class="btn btn-secondary w-100 mt-2">
+                                <i class="fas fa-times"></i> Clear All Filters
+                            </a>
+                        }
+                    </form>
+                </div>
+            </div>
+
+            <!-- Stats Panel -->
+            <div class="card mt-3">
+                <div class="card-body">
+                    <h6 class="card-title">Results</h6>
+                    <p class="card-text">
+                        Found <strong>@Model.Recipes.Count</strong> recipes
+                    </p>
+                </div>
+            </div>
+        </div>
+
+        <div class="col-md-9">
+            <!-- Recipe Results -->
+            <div class="d-flex justify-content-between align-items-center mb-3">
+                <h2>Recipes</h2>
+                <a href="@Url.Action("Create")" class="btn btn-success">
+                    <i class="fas fa-plus"></i> Add New Recipe
+                </a>
+            </div>
+
+            @if (Model.Recipes.Any())
+            {
+                <div class="row">
+                    @foreach (var recipe in Model.Recipes)
+                    {
+                        <div class="col-md-6 col-lg-4 mb-4">
+                            <div class="card h-100">
+                                @* Images disabled on index for performance - only show on details page *@
+                                <div class="card-body">
+                                    <h5 class="card-title">@recipe.Title</h5>
+                                    <p class="card-text">@recipe.Description</p>
+
+                                    @if (!string.IsNullOrEmpty(recipe.Difficulty))
+                                    {
+                                        <div class="mb-2">
+                                            <span class="badge bg-info">@recipe.Difficulty</span>
+                                        </div>
+                                    }
+
+                                    @if (!string.IsNullOrEmpty(recipe.Time))
+                                    {
+                                        <div class="mb-2">
+                                            <small class="text-muted">
+                                                <i class="fas fa-clock"></i> @recipe.Time
+                                            </small>
+                                        </div>
+                                    }
+
+                                    @if (!string.IsNullOrEmpty(recipe.Url))
+                                    {
+                                        <div class="mb-2">
+                                            <a href="@recipe.Url" target="_blank" class="btn btn-sm btn-outline-primary">
+                                                <i class="fas fa-external-link-alt"></i> View Recipe
+                                            </a>
+                                        </div>
+                                    }
+                                </div>
+                                <div class="card-footer">
+                                    <div class="btn-group w-100" role="group">
+                                        <a href="@Url.Action("Details", new { id = recipe.Id })"
+                                            class="btn btn-outline-primary btn-sm">
+                                            <i class="fas fa-eye"></i> Details
+                                        </a>
+                                        <a href="@Url.Action("Edit", new { id = recipe.Id })"
+                                            class="btn btn-outline-warning btn-sm">
+                                            <i class="fas fa-edit"></i> Edit
+                                        </a>
+                                        <a href="@Url.Action("Delete", new { id = recipe.Id })"
+                                            class="btn btn-outline-danger btn-sm">
+                                            <i class="fas fa-trash"></i> Delete
+                                        </a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    }
+                </div>
+            }
+            else
+            {
+                <div class="alert alert-info">
+                    <i class="fas fa-info-circle"></i>
+                    @if (!string.IsNullOrEmpty(Model.SearchTerm))
+                    {
+                        <span>No recipes found matching your search criteria.</span>
+                    }
+                    else
+                    {
+                        <span>No recipes found in the database.</span>
+                    }
+                </div>
+            }
+        </div>
+    </div>
+</div>
+
+@section Scripts {
+    <script>
+        // Auto-submit search after typing (debounced)
+        let searchTimeout;
+        document.getElementById('searchTerm').addEventListener('input', function () {
+            clearTimeout(searchTimeout);
+            searchTimeout = setTimeout(() => {
+                if (this.value.length > 2 || this.value.length === 0) {
+                    this.form.submit();
+                }
+            }, 500);
+        });
+    </script>
+}

+ 60 - 0
Views/Recipe/InspectDatabase.cshtml

@@ -0,0 +1,60 @@
+@{
+    ViewData["Title"] = "Database Inspector";
+}
+
+<h2>Database Structure Inspector</h2>
+
+@if (ViewBag.Error != null)
+{
+    <div class="alert alert-danger">
+        <strong>Error:</strong> @ViewBag.Error
+    </div>
+}
+else
+{
+    <h3>Tables in Database:</h3>
+    @if (ViewBag.Tables != null)
+    {
+        <ul>
+            @foreach (string table in ViewBag.Tables)
+            {
+                <li>@table @(table.ToLower().Contains("image") ? " <strong>(IMAGE TABLE FOUND!)</strong>" : "")</li>
+            }
+        </ul>
+        
+        <p><strong>Total tables found:</strong> @ViewBag.Tables.Count</p>
+    }
+
+    <h3>Image Table Status:</h3>
+    <p><strong>Image table exists:</strong> @ViewBag.ImageTableExists</p>
+    
+    @if (ViewBag.ImageTableName != null)
+    {
+        <p><strong>Image table name:</strong> @ViewBag.ImageTableName</p>
+    }
+
+    @if (ViewBag.ImageTableColumns != null)
+    {
+        <h4>Image Table Columns:</h4>
+        <ul>
+            @foreach (string column in ViewBag.ImageTableColumns)
+            {
+                <li>@column</li>
+            }
+        </ul>
+        
+        @if (ViewBag.ImageRecordCount != null)
+        {
+            <p><strong>Sample records found:</strong> @ViewBag.ImageRecordCount</p>
+        }
+    }
+
+    @if (ViewBag.ImageTableError != null)
+    {
+        <div class="alert alert-warning">
+            <strong>Image Table Error:</strong> @ViewBag.ImageTableError
+        </div>
+    }
+}
+
+<a href="@Url.Action("Index", "Recipe")" class="btn btn-primary">Back to Recipes</a>

+ 14 - 0
Views/Recipe/SimpleTest.cshtml

@@ -0,0 +1,14 @@
+@{
+    ViewData["Title"] = "Database Test";
+}
+
+<h2>Database Connection Test</h2>
+
+<p>This is a simple test to check if we can connect to your database.</p>
+
+<a href="@Url.Action("Api", "Recipe")" class="btn btn-primary">Test Database Connection (JSON API)</a>
+
+<hr>
+
+<h3>Manual Test</h3>
+<p>You should be able to see recipes from your database here once the connection is working.</p>

+ 134 - 0
Views/Recipe/TestDatabase.cshtml

@@ -0,0 +1,134 @@
+@{
+    ViewData["Title"] = "Database Test";
+}
+
+<div class="container mt-4">
+    <h2>Database Connection Test</h2>
+    
+    <div class="alert @(ViewBag.Error != null ? "alert-danger" : "alert-success")">
+        <h4>@ViewBag.ConnectionStatus</h4>
+        @if (ViewBag.Error != null)
+        {
+            <p><strong>Error:</strong> @ViewBag.Error</p>
+        }
+        @if (ViewBag.RecipeCount != null)
+        {
+            <p><strong>Recipes in database:</strong> @ViewBag.RecipeCount</p>
+        }
+        @if (ViewBag.TableError != null)
+        {
+            <p><strong>Table Error:</strong> @ViewBag.TableError</p>
+        }
+    </div>
+
+    @if (ViewBag.Tables != null)
+    {
+        <div class="card">
+            <div class="card-header">
+                <h5>Tables in Database 'recept'</h5>
+            </div>
+            <div class="card-body">
+                @if (((List<string>)ViewBag.Tables).Any())
+                {
+                    <ul class="list-group">
+                        @foreach (var table in (List<string>)ViewBag.Tables)
+                        {
+                            <li class="list-group-item">
+                                @table
+                                @if (table.ToLower().Contains("recepie"))
+                                {
+                                    <span class="badge bg-success ms-2">Recipe Related</span>
+                                }
+                            </li>
+                        }
+                    </ul>
+                }
+                else
+                {
+                    <p class="text-muted">No tables found in the database.</p>
+                }
+            </div>
+        </div>
+    }
+
+    @if (ViewBag.RecepieColumns != null)
+    {
+        <div class="card mt-3">
+            <div class="card-header">
+                <h5>Structure of 'recepie' table</h5>
+            </div>
+            <div class="card-body">
+                <div class="table-responsive">
+                    <table class="table table-striped">
+                        <thead>
+                            <tr>
+                                <th>Column Name</th>
+                                <th>Data Type</th>
+                                <th>Nullable</th>
+                                <th>Key</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            @foreach (var column in (List<dynamic>)ViewBag.RecepieColumns)
+                            {
+                                <tr>
+                                    <td><strong>@column.Name</strong></td>
+                                    <td>@column.Type</td>
+                                    <td>@column.Nullable</td>
+                                    <td>@column.Key</td>
+                                </tr>
+                            }
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    }
+
+    @if (ViewBag.SampleData != null && ViewBag.ColumnNames != null)
+    {
+        <div class="card mt-3">
+            <div class="card-header">
+                <h5>Sample Data from 'recepie' table</h5>
+            </div>
+            <div class="card-body">
+                <div class="table-responsive">
+                    <table class="table table-striped table-sm">
+                        <thead>
+                            <tr>
+                                @foreach (var columnName in (List<string>)ViewBag.ColumnNames)
+                                {
+                                    <th>@columnName</th>
+                                }
+                            </tr>
+                        </thead>
+                        <tbody>
+                            @foreach (var row in (List<Dictionary<string, object>>)ViewBag.SampleData)
+                            {
+                                <tr>
+                                    @foreach (var columnName in (List<string>)ViewBag.ColumnNames)
+                                    {
+                                        <td>
+                                            @{
+                                                var value = row[columnName]?.ToString() ?? "NULL";
+                                                if (value.Length > 50)
+                                                {
+                                                    value = value.Substring(0, 47) + "...";
+                                                }
+                                            }
+                                            @value
+                                        </td>
+                                    }
+                                </tr>
+                            }
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    }
+
+    <div class="mt-3">
+        <a href="@Url.Action("Index")" class="btn btn-primary">Back to Recipes</a>
+    </div>
+</div>

+ 25 - 0
Views/Shared/Error.cshtml

@@ -0,0 +1,25 @@
+@model ErrorViewModel
+@{
+    ViewData["Title"] = "Error";
+}
+
+<h1 class="text-danger">Error.</h1>
+<h2 class="text-danger">An error occurred while processing your request.</h2>
+
+@if (Model.ShowRequestId)
+{
+    <p>
+        <strong>Request ID:</strong> <code>@Model.RequestId</code>
+    </p>
+}
+
+<h3>Development Mode</h3>
+<p>
+    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
+</p>
+<p>
+    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+    It can result in displaying sensitive information from exceptions to end users.
+    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+    and restarting the app.
+</p>

+ 59 - 0
Views/Shared/_Layout.cshtml

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>@ViewData["Title"] - Recipe Manager</title>
+    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
+    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
+    <link rel="stylesheet" href="~/_.styles.css" asp-append-version="true" />
+</head>
+
+<body>
+    <header>
+        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-primary border-bottom box-shadow mb-3">
+            <div class="container-fluid">
+                <a class="navbar-brand" asp-area="" asp-controller="Recipe" asp-action="Index">
+                    <i class="fas fa-utensils"></i> Recipe Manager
+                </a>
+                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse"
+                    aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
+                    <ul class="navbar-nav flex-grow-1">
+                        <li class="nav-item">
+                            <a class="nav-link" asp-area="" asp-controller="Recipe" asp-action="Index">
+                                <i class="fas fa-home"></i> All Recipes
+                            </a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link" asp-area="" asp-controller="Recipe" asp-action="Create">
+                                <i class="fas fa-plus"></i> Add Recipe
+                            </a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </nav>
+    </header>
+    <div class="container-fluid">
+        <main role="main" class="pb-3">
+            @RenderBody()
+        </main>
+    </div>
+
+    <footer class="border-top footer text-muted mt-5">
+        <div class="container">
+            &copy; @DateTime.Now.Year - Recipe Manager - Your Personal Recipe Collection
+        </div>
+    </footer>
+    <script src="~/lib/jquery/dist/jquery.min.js"></script>
+    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
+    <script src="~/js/site.js" asp-append-version="true"></script>
+    @await RenderSectionAsync("Scripts", required: false)
+</body>
+
+</html>

+ 48 - 0
Views/Shared/_Layout.cshtml.css

@@ -0,0 +1,48 @@
+/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
+for details on configuring this project to bundle and minify static web assets. */
+
+a.navbar-brand {
+  white-space: normal;
+  text-align: center;
+  word-break: break-all;
+}
+
+a {
+  color: #0077cc;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #1b6ec2;
+  border-color: #1861ac;
+}
+
+.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
+  color: #fff;
+  background-color: #1b6ec2;
+  border-color: #1861ac;
+}
+
+.border-top {
+  border-top: 1px solid #e5e5e5;
+}
+.border-bottom {
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.box-shadow {
+  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+}
+
+button.accept-policy {
+  font-size: 1rem;
+  line-height: inherit;
+}
+
+.footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  white-space: nowrap;
+  line-height: 60px;
+}

+ 2 - 0
Views/Shared/_ValidationScriptsPartial.cshtml

@@ -0,0 +1,2 @@
+<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
+<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

+ 3 - 0
Views/_ViewImports.cshtml

@@ -0,0 +1,3 @@
+@using _
+@using _.Models
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

+ 3 - 0
Views/_ViewStart.cshtml

@@ -0,0 +1,3 @@
+@{
+    Layout = "_Layout";
+}

+ 8 - 0
appsettings.Development.json

@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}

+ 9 - 0
appsettings.json

@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

BIN
bin/Debug/net8.0/Humanizer.dll


BIN
bin/Debug/net8.0/Microsoft.Bcl.AsyncInterfaces.dll


BIN
bin/Debug/net8.0/Microsoft.Build.Locator.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.dll


BIN
bin/Debug/net8.0/Microsoft.CodeAnalysis.dll


BIN
bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll


BIN
bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Design.dll


BIN
bin/Debug/net8.0/Microsoft.EntityFrameworkCore.Relational.dll


BIN
bin/Debug/net8.0/Microsoft.EntityFrameworkCore.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Caching.Abstractions.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Caching.Memory.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.DependencyModel.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Logging.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Options.dll


BIN
bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll


BIN
bin/Debug/net8.0/Mono.TextTemplating.dll


BIN
bin/Debug/net8.0/MySqlConnector.dll


BIN
bin/Debug/net8.0/Pomelo.EntityFrameworkCore.MySql.dll


+ 973 - 0
bin/Debug/net8.0/Recepie.deps.json

@@ -0,0 +1,973 @@
+{
+  "runtimeTarget": {
+    "name": ".NETCoreApp,Version=v8.0",
+    "signature": ""
+  },
+  "compilationOptions": {},
+  "targets": {
+    ".NETCoreApp,Version=v8.0": {
+      "Recepie/1.0.0": {
+        "dependencies": {
+          "Microsoft.EntityFrameworkCore": "9.0.9",
+          "Microsoft.EntityFrameworkCore.Tools": "9.0.9",
+          "Pomelo.EntityFrameworkCore.MySql": "9.0.0"
+        },
+        "runtime": {
+          "Recepie.dll": {}
+        }
+      },
+      "Humanizer.Core/2.14.1": {
+        "runtime": {
+          "lib/net6.0/Humanizer.dll": {
+            "assemblyVersion": "2.14.0.0",
+            "fileVersion": "2.14.1.48190"
+          }
+        }
+      },
+      "Microsoft.Bcl.AsyncInterfaces/7.0.0": {
+        "runtime": {
+          "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "Microsoft.Build.Framework/17.8.3": {},
+      "Microsoft.Build.Locator/1.7.8": {
+        "runtime": {
+          "lib/net6.0/Microsoft.Build.Locator.dll": {
+            "assemblyVersion": "1.0.0.0",
+            "fileVersion": "1.7.8.28074"
+          }
+        }
+      },
+      "Microsoft.CodeAnalysis.Analyzers/3.3.4": {},
+      "Microsoft.CodeAnalysis.Common/4.8.0": {
+        "dependencies": {
+          "Microsoft.CodeAnalysis.Analyzers": "3.3.4",
+          "System.Collections.Immutable": "7.0.0",
+          "System.Reflection.Metadata": "7.0.0",
+          "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+        },
+        "runtime": {
+          "lib/net7.0/Microsoft.CodeAnalysis.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          }
+        },
+        "resources": {
+          "lib/net7.0/cs/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "cs"
+          },
+          "lib/net7.0/de/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "de"
+          },
+          "lib/net7.0/es/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "es"
+          },
+          "lib/net7.0/fr/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "fr"
+          },
+          "lib/net7.0/it/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "it"
+          },
+          "lib/net7.0/ja/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "ja"
+          },
+          "lib/net7.0/ko/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "ko"
+          },
+          "lib/net7.0/pl/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "pl"
+          },
+          "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "pt-BR"
+          },
+          "lib/net7.0/ru/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "ru"
+          },
+          "lib/net7.0/tr/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "tr"
+          },
+          "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "zh-Hans"
+          },
+          "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll": {
+            "locale": "zh-Hant"
+          }
+        }
+      },
+      "Microsoft.CodeAnalysis.CSharp/4.8.0": {
+        "dependencies": {
+          "Microsoft.CodeAnalysis.Common": "4.8.0"
+        },
+        "runtime": {
+          "lib/net7.0/Microsoft.CodeAnalysis.CSharp.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          }
+        },
+        "resources": {
+          "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "cs"
+          },
+          "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "de"
+          },
+          "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "es"
+          },
+          "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "fr"
+          },
+          "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "it"
+          },
+          "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "ja"
+          },
+          "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "ko"
+          },
+          "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "pl"
+          },
+          "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "pt-BR"
+          },
+          "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "ru"
+          },
+          "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "tr"
+          },
+          "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "zh-Hans"
+          },
+          "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll": {
+            "locale": "zh-Hant"
+          }
+        }
+      },
+      "Microsoft.CodeAnalysis.CSharp.Workspaces/4.8.0": {
+        "dependencies": {
+          "Humanizer.Core": "2.14.1",
+          "Microsoft.CodeAnalysis.CSharp": "4.8.0",
+          "Microsoft.CodeAnalysis.Common": "4.8.0",
+          "Microsoft.CodeAnalysis.Workspaces.Common": "4.8.0"
+        },
+        "runtime": {
+          "lib/net7.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          }
+        },
+        "resources": {
+          "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "cs"
+          },
+          "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "de"
+          },
+          "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "es"
+          },
+          "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "fr"
+          },
+          "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "it"
+          },
+          "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "ja"
+          },
+          "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "ko"
+          },
+          "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "pl"
+          },
+          "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "pt-BR"
+          },
+          "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "ru"
+          },
+          "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "tr"
+          },
+          "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "zh-Hans"
+          },
+          "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": {
+            "locale": "zh-Hant"
+          }
+        }
+      },
+      "Microsoft.CodeAnalysis.Workspaces.Common/4.8.0": {
+        "dependencies": {
+          "Humanizer.Core": "2.14.1",
+          "Microsoft.Bcl.AsyncInterfaces": "7.0.0",
+          "Microsoft.CodeAnalysis.Common": "4.8.0",
+          "System.Composition": "7.0.0",
+          "System.IO.Pipelines": "9.0.9",
+          "System.Threading.Channels": "7.0.0"
+        },
+        "runtime": {
+          "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          }
+        },
+        "resources": {
+          "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "cs"
+          },
+          "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "de"
+          },
+          "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "es"
+          },
+          "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "fr"
+          },
+          "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "it"
+          },
+          "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "ja"
+          },
+          "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "ko"
+          },
+          "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "pl"
+          },
+          "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "pt-BR"
+          },
+          "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "ru"
+          },
+          "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "tr"
+          },
+          "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "zh-Hans"
+          },
+          "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll": {
+            "locale": "zh-Hant"
+          }
+        }
+      },
+      "Microsoft.CodeAnalysis.Workspaces.MSBuild/4.8.0": {
+        "dependencies": {
+          "Microsoft.Build.Framework": "17.8.3",
+          "Microsoft.CodeAnalysis.Common": "4.8.0",
+          "Microsoft.CodeAnalysis.Workspaces.Common": "4.8.0",
+          "System.Text.Json": "9.0.9"
+        },
+        "runtime": {
+          "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          },
+          "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll": {
+            "assemblyVersion": "4.8.0.0",
+            "fileVersion": "4.800.23.55801"
+          }
+        },
+        "resources": {
+          "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "cs"
+          },
+          "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "de"
+          },
+          "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "es"
+          },
+          "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "fr"
+          },
+          "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "it"
+          },
+          "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "ja"
+          },
+          "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "ko"
+          },
+          "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "pl"
+          },
+          "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "pt-BR"
+          },
+          "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "ru"
+          },
+          "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "tr"
+          },
+          "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "zh-Hans"
+          },
+          "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
+            "locale": "zh-Hant"
+          }
+        }
+      },
+      "Microsoft.EntityFrameworkCore/9.0.9": {
+        "dependencies": {
+          "Microsoft.EntityFrameworkCore.Abstractions": "9.0.9",
+          "Microsoft.EntityFrameworkCore.Analyzers": "9.0.9",
+          "Microsoft.Extensions.Caching.Memory": "9.0.9",
+          "Microsoft.Extensions.Logging": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.EntityFrameworkCore.dll": {
+            "assemblyVersion": "9.0.9.0",
+            "fileVersion": "9.0.925.41909"
+          }
+        }
+      },
+      "Microsoft.EntityFrameworkCore.Abstractions/9.0.9": {
+        "runtime": {
+          "lib/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll": {
+            "assemblyVersion": "9.0.9.0",
+            "fileVersion": "9.0.925.41909"
+          }
+        }
+      },
+      "Microsoft.EntityFrameworkCore.Analyzers/9.0.9": {},
+      "Microsoft.EntityFrameworkCore.Design/9.0.9": {
+        "dependencies": {
+          "Humanizer.Core": "2.14.1",
+          "Microsoft.Build.Framework": "17.8.3",
+          "Microsoft.Build.Locator": "1.7.8",
+          "Microsoft.CodeAnalysis.CSharp": "4.8.0",
+          "Microsoft.CodeAnalysis.CSharp.Workspaces": "4.8.0",
+          "Microsoft.CodeAnalysis.Workspaces.MSBuild": "4.8.0",
+          "Microsoft.EntityFrameworkCore.Relational": "9.0.9",
+          "Microsoft.Extensions.Caching.Memory": "9.0.9",
+          "Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
+          "Microsoft.Extensions.DependencyModel": "9.0.9",
+          "Microsoft.Extensions.Logging": "9.0.9",
+          "Mono.TextTemplating": "3.0.0",
+          "System.Text.Json": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.EntityFrameworkCore.Design.dll": {
+            "assemblyVersion": "9.0.9.0",
+            "fileVersion": "9.0.925.41909"
+          }
+        }
+      },
+      "Microsoft.EntityFrameworkCore.Relational/9.0.9": {
+        "dependencies": {
+          "Microsoft.EntityFrameworkCore": "9.0.9",
+          "Microsoft.Extensions.Caching.Memory": "9.0.9",
+          "Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Logging": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.EntityFrameworkCore.Relational.dll": {
+            "assemblyVersion": "9.0.9.0",
+            "fileVersion": "9.0.925.41909"
+          }
+        }
+      },
+      "Microsoft.EntityFrameworkCore.Tools/9.0.9": {
+        "dependencies": {
+          "Microsoft.EntityFrameworkCore.Design": "9.0.9"
+        }
+      },
+      "Microsoft.Extensions.Caching.Abstractions/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.Primitives": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Caching.Memory/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.Caching.Abstractions": "9.0.9",
+          "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Logging.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Options": "9.0.9",
+          "Microsoft.Extensions.Primitives": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Configuration.Abstractions/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.Primitives": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.DependencyInjection/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.DependencyInjection.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.9": {
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.DependencyModel/9.0.9": {
+        "dependencies": {
+          "System.Text.Encodings.Web": "9.0.9",
+          "System.Text.Json": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.DependencyModel.dll": {
+            "assemblyVersion": "9.0.0.9",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Logging/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.DependencyInjection": "9.0.9",
+          "Microsoft.Extensions.Logging.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Options": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Logging.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Logging.Abstractions/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
+          "System.Diagnostics.DiagnosticSource": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Options/9.0.9": {
+        "dependencies": {
+          "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Primitives": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Options.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Microsoft.Extensions.Primitives/9.0.9": {
+        "runtime": {
+          "lib/net8.0/Microsoft.Extensions.Primitives.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "Mono.TextTemplating/3.0.0": {
+        "dependencies": {
+          "System.CodeDom": "6.0.0"
+        },
+        "runtime": {
+          "lib/net6.0/Mono.TextTemplating.dll": {
+            "assemblyVersion": "3.0.0.0",
+            "fileVersion": "3.0.0.1"
+          }
+        }
+      },
+      "MySqlConnector/2.4.0": {
+        "dependencies": {
+          "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
+          "Microsoft.Extensions.Logging.Abstractions": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/MySqlConnector.dll": {
+            "assemblyVersion": "2.0.0.0",
+            "fileVersion": "2.4.0.0"
+          }
+        }
+      },
+      "Pomelo.EntityFrameworkCore.MySql/9.0.0": {
+        "dependencies": {
+          "Microsoft.EntityFrameworkCore.Relational": "9.0.9",
+          "MySqlConnector": "2.4.0"
+        },
+        "runtime": {
+          "lib/net8.0/Pomelo.EntityFrameworkCore.MySql.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.0.0"
+          }
+        }
+      },
+      "System.CodeDom/6.0.0": {
+        "runtime": {
+          "lib/net6.0/System.CodeDom.dll": {
+            "assemblyVersion": "6.0.0.0",
+            "fileVersion": "6.0.21.52210"
+          }
+        }
+      },
+      "System.Collections.Immutable/7.0.0": {},
+      "System.Composition/7.0.0": {
+        "dependencies": {
+          "System.Composition.AttributedModel": "7.0.0",
+          "System.Composition.Convention": "7.0.0",
+          "System.Composition.Hosting": "7.0.0",
+          "System.Composition.Runtime": "7.0.0",
+          "System.Composition.TypedParts": "7.0.0"
+        }
+      },
+      "System.Composition.AttributedModel/7.0.0": {
+        "runtime": {
+          "lib/net7.0/System.Composition.AttributedModel.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "System.Composition.Convention/7.0.0": {
+        "dependencies": {
+          "System.Composition.AttributedModel": "7.0.0"
+        },
+        "runtime": {
+          "lib/net7.0/System.Composition.Convention.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "System.Composition.Hosting/7.0.0": {
+        "dependencies": {
+          "System.Composition.Runtime": "7.0.0"
+        },
+        "runtime": {
+          "lib/net7.0/System.Composition.Hosting.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "System.Composition.Runtime/7.0.0": {
+        "runtime": {
+          "lib/net7.0/System.Composition.Runtime.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "System.Composition.TypedParts/7.0.0": {
+        "dependencies": {
+          "System.Composition.AttributedModel": "7.0.0",
+          "System.Composition.Hosting": "7.0.0",
+          "System.Composition.Runtime": "7.0.0"
+        },
+        "runtime": {
+          "lib/net7.0/System.Composition.TypedParts.dll": {
+            "assemblyVersion": "7.0.0.0",
+            "fileVersion": "7.0.22.51805"
+          }
+        }
+      },
+      "System.Diagnostics.DiagnosticSource/9.0.9": {
+        "runtime": {
+          "lib/net8.0/System.Diagnostics.DiagnosticSource.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "System.IO.Pipelines/9.0.9": {
+        "runtime": {
+          "lib/net8.0/System.IO.Pipelines.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "System.Reflection.Metadata/7.0.0": {
+        "dependencies": {
+          "System.Collections.Immutable": "7.0.0"
+        }
+      },
+      "System.Runtime.CompilerServices.Unsafe/6.0.0": {},
+      "System.Text.Encodings.Web/9.0.9": {
+        "runtime": {
+          "lib/net8.0/System.Text.Encodings.Web.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        },
+        "runtimeTargets": {
+          "runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll": {
+            "rid": "browser",
+            "assetType": "runtime",
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "System.Text.Json/9.0.9": {
+        "dependencies": {
+          "System.IO.Pipelines": "9.0.9",
+          "System.Text.Encodings.Web": "9.0.9"
+        },
+        "runtime": {
+          "lib/net8.0/System.Text.Json.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.925.41916"
+          }
+        }
+      },
+      "System.Threading.Channels/7.0.0": {}
+    }
+  },
+  "libraries": {
+    "Recepie/1.0.0": {
+      "type": "project",
+      "serviceable": false,
+      "sha512": ""
+    },
+    "Humanizer.Core/2.14.1": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==",
+      "path": "humanizer.core/2.14.1",
+      "hashPath": "humanizer.core.2.14.1.nupkg.sha512"
+    },
+    "Microsoft.Bcl.AsyncInterfaces/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-3aeMZ1N0lJoSyzqiP03hqemtb1BijhsJADdobn/4nsMJ8V1H+CrpuduUe4hlRdx+ikBQju1VGjMD1GJ3Sk05Eg==",
+      "path": "microsoft.bcl.asyncinterfaces/7.0.0",
+      "hashPath": "microsoft.bcl.asyncinterfaces.7.0.0.nupkg.sha512"
+    },
+    "Microsoft.Build.Framework/17.8.3": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-NrQZJW8TlKVPx72yltGb8SVz3P5mNRk9fNiD/ao8jRSk48WqIIdCn99q4IjlVmPcruuQ+yLdjNQLL8Rb4c916g==",
+      "path": "microsoft.build.framework/17.8.3",
+      "hashPath": "microsoft.build.framework.17.8.3.nupkg.sha512"
+    },
+    "Microsoft.Build.Locator/1.7.8": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-sPy10x527Ph16S2u0yGME4S6ohBKJ69WfjeGG/bvELYeZVmJdKjxgnlL8cJJJLGV/cZIRqSfB12UDB8ICakOog==",
+      "path": "microsoft.build.locator/1.7.8",
+      "hashPath": "microsoft.build.locator.1.7.8.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.Analyzers/3.3.4": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-AxkxcPR+rheX0SmvpLVIGLhOUXAKG56a64kV9VQZ4y9gR9ZmPXnqZvHJnmwLSwzrEP6junUF11vuc+aqo5r68g==",
+      "path": "microsoft.codeanalysis.analyzers/3.3.4",
+      "hashPath": "microsoft.codeanalysis.analyzers.3.3.4.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.Common/4.8.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-/jR+e/9aT+BApoQJABlVCKnnggGQbvGh7BKq2/wI1LamxC+LbzhcLj4Vj7gXCofl1n4E521YfF9w0WcASGg/KA==",
+      "path": "microsoft.codeanalysis.common/4.8.0",
+      "hashPath": "microsoft.codeanalysis.common.4.8.0.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.CSharp/4.8.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-+3+qfdb/aaGD8PZRCrsdobbzGs1m9u119SkkJt8e/mk3xLJz/udLtS2T6nY27OTXxBBw10HzAbC8Z9w08VyP/g==",
+      "path": "microsoft.codeanalysis.csharp/4.8.0",
+      "hashPath": "microsoft.codeanalysis.csharp.4.8.0.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.CSharp.Workspaces/4.8.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-3amm4tq4Lo8/BGvg9p3BJh3S9nKq2wqCXfS7138i69TUpo/bD+XvD0hNurpEBtcNZhi1FyutiomKJqVF39ugYA==",
+      "path": "microsoft.codeanalysis.csharp.workspaces/4.8.0",
+      "hashPath": "microsoft.codeanalysis.csharp.workspaces.4.8.0.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.Workspaces.Common/4.8.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-LXyV+MJKsKRu3FGJA3OmSk40OUIa/dQCFLOnm5X8MNcujx7hzGu8o+zjXlb/cy5xUdZK2UKYb9YaQ2E8m9QehQ==",
+      "path": "microsoft.codeanalysis.workspaces.common/4.8.0",
+      "hashPath": "microsoft.codeanalysis.workspaces.common.4.8.0.nupkg.sha512"
+    },
+    "Microsoft.CodeAnalysis.Workspaces.MSBuild/4.8.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-IEYreI82QZKklp54yPHxZNG9EKSK6nHEkeuf+0Asie9llgS1gp0V1hw7ODG+QyoB7MuAnNQHmeV1Per/ECpv6A==",
+      "path": "microsoft.codeanalysis.workspaces.msbuild/4.8.0",
+      "hashPath": "microsoft.codeanalysis.workspaces.msbuild.4.8.0.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-zkt5yQgnpWKX3rOxn+ZcV23Aj0296XCTqg4lx1hKY+wMXBgkn377UhBrY/A4H6kLpNT7wqZN98xCV0YHXu9VRA==",
+      "path": "microsoft.entityframeworkcore/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore.Abstractions/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-QdM2k3Mnip2QsaxJbCI95dc2SajRMENdmaMhVKj4jPC5dmkoRcu3eEdvZAgDbd4bFVV1jtPGdHtXewtoBMlZqA==",
+      "path": "microsoft.entityframeworkcore.abstractions/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.abstractions.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore.Analyzers/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-uiKeU/qR0YpaDUa4+g0rAjKCuwfq8YWZGcpPptnFWIr1K7dXQTm/15D2HDwwU4ln3Uf66krYybymuY58ua4hhw==",
+      "path": "microsoft.entityframeworkcore.analyzers/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.analyzers.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore.Design/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-cFxH70tohWe3ugCjLhZB01mR7WHpg5dEK6zHsbkDFfpLxWT+HoZQKgchTJgF4bPWBPTyrlYlqfPY212fFtmJjg==",
+      "path": "microsoft.entityframeworkcore.design/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.design.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore.Relational/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-SonFU9a8x4jZIhIBtCw1hIE3QKjd4c7Y3mjptoh682dfQe7K9pUPGcEV/sk4n8AJdq4fkyJPCaOdYaObhae/Iw==",
+      "path": "microsoft.entityframeworkcore.relational/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.relational.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.EntityFrameworkCore.Tools/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-Q8n1PXXJApa1qX8HI3r/YuHoJ1HuLwjI2hLqaCV9K9pqQhGpi6Z38laOYwL2ElUOTWCxTKMDEMMYWfPlw6rwgg==",
+      "path": "microsoft.entityframeworkcore.tools/9.0.9",
+      "hashPath": "microsoft.entityframeworkcore.tools.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Caching.Abstractions/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-NgtRHOdPrAEacfjXLSrH/SRrSqGf6Vaa6d16mW2yoyJdg7AJr0BnBvxkv7PkCm/CHVyzojTK7Y+oUDEulqY1Qw==",
+      "path": "microsoft.extensions.caching.abstractions/9.0.9",
+      "hashPath": "microsoft.extensions.caching.abstractions.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Caching.Memory/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-ln31BtsDsBQxykJgxuCtiUXWRET9FmqeEq0BpPIghkYtGpDDVs8ZcLHAjCCzbw6aGoLek4Z7JaDjSO/CjOD0iw==",
+      "path": "microsoft.extensions.caching.memory/9.0.9",
+      "hashPath": "microsoft.extensions.caching.memory.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Configuration.Abstractions/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-p5RKAY9POvs3axwA/AQRuJeM8AHuE8h4qbP1NxQeGm0ep46aXz1oCLAp/oOYxX1GsjStgdhHrN3XXLLXr0+b3w==",
+      "path": "microsoft.extensions.configuration.abstractions/9.0.9",
+      "hashPath": "microsoft.extensions.configuration.abstractions.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.DependencyInjection/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-zQV2WOSP+3z1EuK91ULxfGgo2Y75bTRnmJHp08+w/YXAyekZutX/qCd88/HOMNh35MDW9mJJJxPpMPS+1Rww8A==",
+      "path": "microsoft.extensions.dependencyinjection/9.0.9",
+      "hashPath": "microsoft.extensions.dependencyinjection.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-/hymojfWbE9AlDOa0mczR44m00Jj+T3+HZO0ZnVTI032fVycI0ZbNOVFP6kqZMcXiLSYXzR2ilcwaRi6dzeGyA==",
+      "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.9",
+      "hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.DependencyModel/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-fNGvKct2De8ghm0Bpfq0iWthtzIWabgOTi+gJhNOPhNJIowXNEUE2eZNW/zNCzrHVA3PXg2yZ+3cWZndC2IqYA==",
+      "path": "microsoft.extensions.dependencymodel/9.0.9",
+      "hashPath": "microsoft.extensions.dependencymodel.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Logging/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-MaCB0Y9hNDs4YLu3HCJbo199WnJT8xSgajG1JYGANz9FkseQ5f3v/llu3HxLI6mjDlu7pa7ps9BLPWjKzsAAzQ==",
+      "path": "microsoft.extensions.logging/9.0.9",
+      "hashPath": "microsoft.extensions.logging.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Logging.Abstractions/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-FEgpSF+Z9StMvrsSViaybOBwR0f0ZZxDm8xV5cSOFiXN/t+ys+rwAlTd/6yG7Ld1gfppgvLcMasZry3GsI9lGA==",
+      "path": "microsoft.extensions.logging.abstractions/9.0.9",
+      "hashPath": "microsoft.extensions.logging.abstractions.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Options/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-loxGGHE1FC2AefwPHzrjPq7X92LQm64qnU/whKfo6oWaceewPUVYQJBJs3S3E2qlWwnCpeZ+dGCPTX+5dgVAuQ==",
+      "path": "microsoft.extensions.options/9.0.9",
+      "hashPath": "microsoft.extensions.options.9.0.9.nupkg.sha512"
+    },
+    "Microsoft.Extensions.Primitives/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-z4pyMePOrl733ltTowbN565PxBw1oAr8IHmIXNDiDqd22nFpYltX9KhrNC/qBWAG1/Zx5MHX+cOYhWJQYCO/iw==",
+      "path": "microsoft.extensions.primitives/9.0.9",
+      "hashPath": "microsoft.extensions.primitives.9.0.9.nupkg.sha512"
+    },
+    "Mono.TextTemplating/3.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-YqueG52R/Xej4VVbKuRIodjiAhV0HR/XVbLbNrJhCZnzjnSjgMJ/dCdV0akQQxavX6hp/LC6rqLGLcXeQYU7XA==",
+      "path": "mono.texttemplating/3.0.0",
+      "hashPath": "mono.texttemplating.3.0.0.nupkg.sha512"
+    },
+    "MySqlConnector/2.4.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-78M+gVOjbdZEDIyXQqcA7EYlCGS3tpbUELHvn6638A2w0pkPI625ixnzsa5staAd3N9/xFmPJtkKDYwsXpFi/w==",
+      "path": "mysqlconnector/2.4.0",
+      "hashPath": "mysqlconnector.2.4.0.nupkg.sha512"
+    },
+    "Pomelo.EntityFrameworkCore.MySql/9.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-cl7S4s6CbJno0LjNxrBHNc2xxmCliR5i40ATPZk/eTywVaAbHCbdc9vbGc3QThvwGjHqrDHT8vY9m1VF/47o0g==",
+      "path": "pomelo.entityframeworkcore.mysql/9.0.0",
+      "hashPath": "pomelo.entityframeworkcore.mysql.9.0.0.nupkg.sha512"
+    },
+    "System.CodeDom/6.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-CPc6tWO1LAer3IzfZufDBRL+UZQcj5uS207NHALQzP84Vp/z6wF0Aa0YZImOQY8iStY0A2zI/e3ihKNPfUm8XA==",
+      "path": "system.codedom/6.0.0",
+      "hashPath": "system.codedom.6.0.0.nupkg.sha512"
+    },
+    "System.Collections.Immutable/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==",
+      "path": "system.collections.immutable/7.0.0",
+      "hashPath": "system.collections.immutable.7.0.0.nupkg.sha512"
+    },
+    "System.Composition/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-tRwgcAkDd85O8Aq6zHDANzQaq380cek9lbMg5Qma46u5BZXq/G+XvIYmu+UI+BIIZ9zssXLYrkTykEqxxvhcmg==",
+      "path": "system.composition/7.0.0",
+      "hashPath": "system.composition.7.0.0.nupkg.sha512"
+    },
+    "System.Composition.AttributedModel/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-2QzClqjElKxgI1jK1Jztnq44/8DmSuTSGGahXqQ4TdEV0h9s2KikQZIgcEqVzR7OuWDFPGLHIprBJGQEPr8fAQ==",
+      "path": "system.composition.attributedmodel/7.0.0",
+      "hashPath": "system.composition.attributedmodel.7.0.0.nupkg.sha512"
+    },
+    "System.Composition.Convention/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-IMhTlpCs4HmlD8B+J8/kWfwX7vrBBOs6xyjSTzBlYSs7W4OET4tlkR/Sg9NG8jkdJH9Mymq0qGdYS1VPqRTBnQ==",
+      "path": "system.composition.convention/7.0.0",
+      "hashPath": "system.composition.convention.7.0.0.nupkg.sha512"
+    },
+    "System.Composition.Hosting/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-eB6gwN9S+54jCTBJ5bpwMOVerKeUfGGTYCzz3QgDr1P55Gg/Wb27ShfPIhLMjmZ3MoAKu8uUSv6fcCdYJTN7Bg==",
+      "path": "system.composition.hosting/7.0.0",
+      "hashPath": "system.composition.hosting.7.0.0.nupkg.sha512"
+    },
+    "System.Composition.Runtime/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-aZJ1Zr5Txe925rbo4742XifEyW0MIni1eiUebmcrP3HwLXZ3IbXUj4MFMUH/RmnJOAQiS401leg/2Sz1MkApDw==",
+      "path": "system.composition.runtime/7.0.0",
+      "hashPath": "system.composition.runtime.7.0.0.nupkg.sha512"
+    },
+    "System.Composition.TypedParts/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-ZK0KNPfbtxVceTwh+oHNGUOYV2WNOHReX2AXipuvkURC7s/jPwoWfsu3SnDBDgofqbiWr96geofdQ2erm/KTHg==",
+      "path": "system.composition.typedparts/7.0.0",
+      "hashPath": "system.composition.typedparts.7.0.0.nupkg.sha512"
+    },
+    "System.Diagnostics.DiagnosticSource/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-8hy61dsFYYSDjT9iTAfygGMU3A0EAnG69x5FUXeKsCjMhBmtTBt4UMUEW3ipprFoorOW6Jw/7hDMjXtlrsOvVQ==",
+      "path": "system.diagnostics.diagnosticsource/9.0.9",
+      "hashPath": "system.diagnostics.diagnosticsource.9.0.9.nupkg.sha512"
+    },
+    "System.IO.Pipelines/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-VySjpsCLprojvat550Flrm3NQB982CPuDzILajqjQihFmrQXZPdQyktIbcpVPJyaExFYtAfY1DpwMdWQuS0kbw==",
+      "path": "system.io.pipelines/9.0.9",
+      "hashPath": "system.io.pipelines.9.0.9.nupkg.sha512"
+    },
+    "System.Reflection.Metadata/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-MclTG61lsD9sYdpNz9xsKBzjsmsfCtcMZYXz/IUr2zlhaTaABonlr1ESeompTgM+Xk+IwtGYU7/voh3YWB/fWw==",
+      "path": "system.reflection.metadata/7.0.0",
+      "hashPath": "system.reflection.metadata.7.0.0.nupkg.sha512"
+    },
+    "System.Runtime.CompilerServices.Unsafe/6.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
+      "path": "system.runtime.compilerservices.unsafe/6.0.0",
+      "hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
+    },
+    "System.Text.Encodings.Web/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bzYTmAcmfelUOCBxvbgsfSr2tq94ydA2gJZAxZRcuNa0LlmlVz8JNHst6RG1qsDujyVYT4vjv06y8sCLbvCXdg==",
+      "path": "system.text.encodings.web/9.0.9",
+      "hashPath": "system.text.encodings.web.9.0.9.nupkg.sha512"
+    },
+    "System.Text.Json/9.0.9": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-NEnpppwq67fRz/OvQRxsEMgetDJsxlxpEsAFO/4PZYbAyAMd4Ol6KS7phc8uDoKPsnbdzRLKobpX303uQwCqdg==",
+      "path": "system.text.json/9.0.9",
+      "hashPath": "system.text.json.9.0.9.nupkg.sha512"
+    },
+    "System.Threading.Channels/7.0.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-qmeeYNROMsONF6ndEZcIQ+VxR4Q/TX/7uIVLJqtwIWL7dDWeh0l1UIqgo4wYyjG//5lUNhwkLDSFl+pAWO6oiA==",
+      "path": "system.threading.channels/7.0.0",
+      "hashPath": "system.threading.channels.7.0.0.nupkg.sha512"
+    }
+  }
+}

BIN
bin/Debug/net8.0/Recepie.dll


BIN
bin/Debug/net8.0/Recepie.exe


BIN
bin/Debug/net8.0/Recepie.pdb


+ 20 - 0
bin/Debug/net8.0/Recepie.runtimeconfig.json

@@ -0,0 +1,20 @@
+{
+  "runtimeOptions": {
+    "tfm": "net8.0",
+    "frameworks": [
+      {
+        "name": "Microsoft.NETCore.App",
+        "version": "8.0.0"
+      },
+      {
+        "name": "Microsoft.AspNetCore.App",
+        "version": "8.0.0"
+      }
+    ],
+    "configProperties": {
+      "System.GC.Server": true,
+      "System.Reflection.NullabilityInfoContext.IsSupported": true,
+      "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
+    }
+  }
+}

File diff suppressed because it is too large
+ 0 - 0
bin/Debug/net8.0/Recepie.staticwebassets.runtime.json


BIN
bin/Debug/net8.0/System.CodeDom.dll


BIN
bin/Debug/net8.0/System.Composition.AttributedModel.dll


BIN
bin/Debug/net8.0/System.Composition.Convention.dll


BIN
bin/Debug/net8.0/System.Composition.Hosting.dll


BIN
bin/Debug/net8.0/System.Composition.Runtime.dll


BIN
bin/Debug/net8.0/System.Composition.TypedParts.dll


BIN
bin/Debug/net8.0/System.Diagnostics.DiagnosticSource.dll


BIN
bin/Debug/net8.0/System.IO.Pipelines.dll


BIN
bin/Debug/net8.0/System.Text.Encodings.Web.dll


BIN
bin/Debug/net8.0/System.Text.Json.dll


+ 8 - 0
bin/Debug/net8.0/appsettings.Development.json

@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}

+ 9 - 0
bin/Debug/net8.0/appsettings.json

@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

BIN
bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll


BIN
bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll


BIN
bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll


BIN
bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll


BIN
bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.resources.dll


BIN
bin/Debug/net8.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll


BIN
bin/Debug/net8.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll


BIN
bin/Debug/net8.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll


BIN
bin/Debug/net8.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll


BIN
bin/Debug/net8.0/de/Microsoft.CodeAnalysis.resources.dll


BIN
bin/Debug/net8.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll


BIN
bin/Debug/net8.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll


BIN
bin/Debug/net8.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll


BIN
bin/Debug/net8.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll


BIN
bin/Debug/net8.0/es/Microsoft.CodeAnalysis.resources.dll


BIN
bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll


BIN
bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll


BIN
bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll


BIN
bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll


BIN
bin/Debug/net8.0/fr/Microsoft.CodeAnalysis.resources.dll


BIN
bin/Debug/net8.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll


Some files were not shown because too many files changed in this diff