From 2ef6e9fc32b544df1d5b653d0bd84226e497db90 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Nov 2025 01:13:36 +0000 Subject: [PATCH] Improve exception handling and add null safety across multiple samples --- .../Data/XmlFavoritesRepository.cs | 88 ++++++++++++++++++- .../ViewModels/EditRecipeViewModel.cs | 14 ++- .../ViewModels/RecipeDetailViewModel.cs | 14 ++- .../ViewModels/SearchResultDetailViewModel.cs | 18 +++- .../Xaminals/Views/CatDetailPage.xaml.cs | 14 ++- .../Xaminals/Views/DogDetailPage.xaml.cs | 14 ++- .../Controllers/TodoItemsController.cs | 48 ++++++++-- .../TodoAPI/Services/TodoRepository.cs | 47 +++++++++- .../Data/XmlFavoritesRepository.cs | 88 ++++++++++++++++++- .../ViewModels/EditRecipeViewModel.cs | 14 ++- .../ViewModels/RecipeDetailViewModel.cs | 14 ++- .../ViewModels/SearchResultDetailViewModel.cs | 18 +++- .../Xaminals/Views/CatDetailPage.xaml.cs | 14 ++- .../Xaminals/Views/DogDetailPage.xaml.cs | 14 ++- .../Controllers/TodoItemsController.cs | 48 ++++++++-- .../TodoAPI/Services/TodoRepository.cs | 47 +++++++++- 16 files changed, 454 insertions(+), 60 deletions(-) diff --git a/10.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs b/10.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs index a3c21cacc..33e0c5328 100644 --- a/10.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs +++ b/10.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs @@ -62,8 +62,40 @@ public async static Task OpenIsolatedStorage(string isol }; } } - catch (Exception) + catch (IOException ex) { + // Log IO errors (file access issues) + System.Diagnostics.Debug.WriteLine($"IO Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (XmlException ex) + { + // Log XML parsing errors (corrupted file) + System.Diagnostics.Debug.WriteLine($"XML Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (InvalidOperationException ex) + { + // Log deserialization errors (schema mismatch) + System.Diagnostics.Debug.WriteLine($"Deserialization Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (Exception ex) + { + // Log unexpected errors + System.Diagnostics.Debug.WriteLine($"Unexpected error loading favorites: {ex.Message}"); return new XmlFavoritesRepository { IsolatedStorageName = isolatedStorageName, @@ -84,8 +116,40 @@ public async static Task OpenFile(string path) repo.IsolatedStorageName = Path.GetFileName(path); return repo; } - catch (Exception) + catch (IOException ex) + { + // Log IO errors (file access issues) + System.Diagnostics.Debug.WriteLine($"IO Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (XmlException ex) + { + // Log XML parsing errors (corrupted file) + System.Diagnostics.Debug.WriteLine($"XML Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (InvalidOperationException ex) + { + // Log deserialization errors (schema mismatch) + System.Diagnostics.Debug.WriteLine($"Deserialization Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (Exception ex) { + // Log unexpected errors + System.Diagnostics.Debug.WriteLine($"Unexpected error opening file: {ex.Message}"); return new XmlFavoritesRepository { IsolatedStorageName = Path.GetFileName(path), @@ -106,9 +170,25 @@ private async Task Commit() using var f = new FileStream(filePath, FileMode.Create, FileAccess.Write); serializer.Serialize(f, this); } - catch (Exception) + catch (IOException ex) + { + // Log IO errors during commit + System.Diagnostics.Debug.WriteLine($"IO Error committing favorites: {ex.Message}"); + } + catch (XmlException ex) + { + // Log XML serialization errors + System.Diagnostics.Debug.WriteLine($"XML Error committing favorites: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + // Log serialization errors + System.Diagnostics.Debug.WriteLine($"Serialization Error committing favorites: {ex.Message}"); + } + catch (Exception ex) { - // Ignore serialization errors + // Log unexpected errors during commit + System.Diagnostics.Debug.WriteLine($"Unexpected error committing favorites: {ex.Message}"); } var ev = Changed; diff --git a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs index 142bf39f4..bbdfae97f 100644 --- a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs +++ b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Recipes.Models; namespace Recipes.ViewModels @@ -104,9 +104,17 @@ public async void LoadItemId(string itemId) RecipeRating = item.RecipeRating; RecipeReview = item.RecipeReview; } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Item"); + Debug.WriteLine($"Argument null error loading recipe for edit: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading recipe for edit: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load recipe item for edit: {ex.Message}"); } } diff --git a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs index 1cb3ae017..05c5d5085 100644 --- a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs +++ b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Recipes.Views; using System.Collections.ObjectModel; using Recipes.Models; @@ -186,9 +186,17 @@ public async void LoadItemId(string itemId) RecipeReviewVisible = !string.IsNullOrEmpty(RecipeReview); } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Item"); + Debug.WriteLine($"Argument null error loading recipe: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading recipe: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load recipe item: {ex.Message}"); } } diff --git a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs index 13b40b495..5ed9df6c7 100644 --- a/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs +++ b/10.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs @@ -1,4 +1,4 @@ -using System.Windows.Input; +using System.Windows.Input; using System.Diagnostics; using Recipes.Models; using System.Collections.ObjectModel; @@ -147,9 +147,21 @@ public void LoadHitId(string hitId) OnPropertyChanged(nameof(Hit)); LoadSearchResultDetails(); } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Hit"); + Debug.WriteLine($"Argument null error loading search result: {ex.Message}"); + } + catch (FormatException ex) + { + Debug.WriteLine($"Format error parsing hit ID: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading search result: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load search result hit: {ex.Message}"); } } diff --git a/10.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs b/10.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs index 9ace2947b..f87839ef6 100644 --- a/10.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs +++ b/10.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs @@ -1,4 +1,4 @@ -using Xaminals.Data; +using Xaminals.Data; using Xaminals.Models; namespace Xaminals.Views @@ -26,9 +26,17 @@ void LoadAnimal(string name) Animal animal = CatData.Cats.FirstOrDefault(a => a.Name == name); BindingContext = animal; } - catch (Exception) + catch (ArgumentNullException ex) { - Console.WriteLine("Failed to load animal."); + System.Diagnostics.Debug.WriteLine($"Argument null error loading cat: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + System.Diagnostics.Debug.WriteLine($"Invalid operation loading cat: {ex.Message}"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to load cat: {ex.Message}"); } } } diff --git a/10.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs b/10.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs index b64d2f451..d0d9e798a 100644 --- a/10.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs +++ b/10.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs @@ -1,4 +1,4 @@ -using Xaminals.Data; +using Xaminals.Data; using Xaminals.Models; namespace Xaminals.Views @@ -26,9 +26,17 @@ void LoadAnimal(string name) Animal animal = DogData.Dogs.FirstOrDefault(a => a.Name == name); BindingContext = animal; } - catch (Exception) + catch (ArgumentNullException ex) { - Console.WriteLine("Failed to load animal."); + System.Diagnostics.Debug.WriteLine($"Argument null error loading dog: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + System.Diagnostics.Debug.WriteLine($"Invalid operation loading dog: {ex.Message}"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to load dog: {ex.Message}"); } } } diff --git a/10.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs b/10.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs index 453d2a351..f2d192b01 100644 --- a/10.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs +++ b/10.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using TodoAPI.Interfaces; using TodoAPI.Models; @@ -54,9 +54,19 @@ public IActionResult Create([FromBody]TodoItem item) } _todoRepository.Insert(item); } - catch (Exception) + catch (ArgumentNullException ex) { - return BadRequest(ErrorCode.CouldNotCreateItem.ToString()); + return BadRequest($"{ErrorCode.CouldNotCreateItem}: {ex.Message}"); + } + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotCreateItem}: {ex.Message}"); + } + catch (Exception ex) + { + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotCreateItem}: An unexpected error occurred"); } return Ok(item); } @@ -79,9 +89,23 @@ public IActionResult Edit([FromBody] TodoItem item) } _todoRepository.Update(item); } - catch (Exception) + catch (ArgumentNullException ex) + { + return BadRequest($"{ErrorCode.CouldNotUpdateItem}: {ex.Message}"); + } + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotUpdateItem}: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + return NotFound($"{ErrorCode.RecordNotFound}: {ex.Message}"); + } + catch (Exception ex) { - return BadRequest(ErrorCode.CouldNotUpdateItem.ToString()); + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotUpdateItem}: An unexpected error occurred"); } return NoContent(); } @@ -100,9 +124,19 @@ public IActionResult Delete(string id) } _todoRepository.Delete(id); } - catch (Exception) + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotDeleteItem}: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + return NotFound($"{ErrorCode.RecordNotFound}: {ex.Message}"); + } + catch (Exception ex) { - return BadRequest(ErrorCode.CouldNotDeleteItem.ToString()); + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotDeleteItem}: An unexpected error occurred"); } return NoContent(); } diff --git a/10.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs b/10.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs index f00692b9a..65cdcba66 100644 --- a/10.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs +++ b/10.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs @@ -1,4 +1,4 @@ -using TodoAPI.Interfaces; +using TodoAPI.Interfaces; using TodoAPI.Models; namespace TodoAPI.Services @@ -29,20 +29,59 @@ public TodoItem Find(string id) public void Insert(TodoItem item) { + if (item == null) + { + throw new ArgumentNullException(nameof(item), "TodoItem cannot be null"); + } + + if (string.IsNullOrWhiteSpace(item.ID)) + { + throw new ArgumentException("TodoItem ID cannot be null or empty", nameof(item)); + } + _todoList.Add(item); } public void Update(TodoItem item) { + if (item == null) + { + throw new ArgumentNullException(nameof(item), "TodoItem cannot be null"); + } + + if (string.IsNullOrWhiteSpace(item.ID)) + { + throw new ArgumentException("TodoItem ID cannot be null or empty", nameof(item)); + } + var todoItem = this.Find(item.ID); + if (todoItem == null) + { + throw new InvalidOperationException($"TodoItem with ID '{item.ID}' not found"); + } + var index = _todoList.IndexOf(todoItem); - _todoList.RemoveAt(index); - _todoList.Insert(index, item); + if (index >= 0) + { + _todoList.RemoveAt(index); + _todoList.Insert(index, item); + } } public void Delete(string id) { - _todoList.Remove(this.Find(id)); + if (string.IsNullOrWhiteSpace(id)) + { + throw new ArgumentException("ID cannot be null or empty", nameof(id)); + } + + var todoItem = this.Find(id); + if (todoItem == null) + { + throw new InvalidOperationException($"TodoItem with ID '{id}' not found"); + } + + _todoList.Remove(todoItem); } private void InitializeData() diff --git a/9.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs b/9.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs index 2b3e5a1c5..c75787c8a 100644 --- a/9.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs +++ b/9.0/Apps/EmployeeDirectory/EmployeeDirectory/Data/XmlFavoritesRepository.cs @@ -63,8 +63,40 @@ public async static Task OpenIsolatedStorage(string isol }; } } - catch (Exception) + catch (IOException ex) { + // Log IO errors (file access issues) + System.Diagnostics.Debug.WriteLine($"IO Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (XmlException ex) + { + // Log XML parsing errors (corrupted file) + System.Diagnostics.Debug.WriteLine($"XML Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (InvalidOperationException ex) + { + // Log deserialization errors (schema mismatch) + System.Diagnostics.Debug.WriteLine($"Deserialization Error loading favorites: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = isolatedStorageName, + People = new List() + }; + } + catch (Exception ex) + { + // Log unexpected errors + System.Diagnostics.Debug.WriteLine($"Unexpected error loading favorites: {ex.Message}"); return new XmlFavoritesRepository { IsolatedStorageName = isolatedStorageName, @@ -85,8 +117,40 @@ public async static Task OpenFile(string path) repo.IsolatedStorageName = Path.GetFileName(path); return repo; } - catch (Exception) + catch (IOException ex) + { + // Log IO errors (file access issues) + System.Diagnostics.Debug.WriteLine($"IO Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (XmlException ex) + { + // Log XML parsing errors (corrupted file) + System.Diagnostics.Debug.WriteLine($"XML Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (InvalidOperationException ex) + { + // Log deserialization errors (schema mismatch) + System.Diagnostics.Debug.WriteLine($"Deserialization Error opening file: {ex.Message}"); + return new XmlFavoritesRepository + { + IsolatedStorageName = Path.GetFileName(path), + People = new List() + }; + } + catch (Exception ex) { + // Log unexpected errors + System.Diagnostics.Debug.WriteLine($"Unexpected error opening file: {ex.Message}"); return new XmlFavoritesRepository { IsolatedStorageName = Path.GetFileName(path), @@ -107,9 +171,25 @@ private async Task Commit() using var f = new FileStream(filePath, FileMode.Create, FileAccess.Write); serializer.Serialize(f, this); } - catch (Exception) + catch (IOException ex) + { + // Log IO errors during commit + System.Diagnostics.Debug.WriteLine($"IO Error committing favorites: {ex.Message}"); + } + catch (XmlException ex) + { + // Log XML serialization errors + System.Diagnostics.Debug.WriteLine($"XML Error committing favorites: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + // Log serialization errors + System.Diagnostics.Debug.WriteLine($"Serialization Error committing favorites: {ex.Message}"); + } + catch (Exception ex) { - // Ignore serialization errors + // Log unexpected errors during commit + System.Diagnostics.Debug.WriteLine($"Unexpected error committing favorites: {ex.Message}"); } var ev = Changed; diff --git a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs index 142bf39f4..bbdfae97f 100644 --- a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs +++ b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/EditRecipeViewModel.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Recipes.Models; namespace Recipes.ViewModels @@ -104,9 +104,17 @@ public async void LoadItemId(string itemId) RecipeRating = item.RecipeRating; RecipeReview = item.RecipeReview; } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Item"); + Debug.WriteLine($"Argument null error loading recipe for edit: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading recipe for edit: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load recipe item for edit: {ex.Message}"); } } diff --git a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs index 1cb3ae017..05c5d5085 100644 --- a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs +++ b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/RecipeDetailViewModel.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Recipes.Views; using System.Collections.ObjectModel; using Recipes.Models; @@ -186,9 +186,17 @@ public async void LoadItemId(string itemId) RecipeReviewVisible = !string.IsNullOrEmpty(RecipeReview); } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Item"); + Debug.WriteLine($"Argument null error loading recipe: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading recipe: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load recipe item: {ex.Message}"); } } diff --git a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs index 13b40b495..5ed9df6c7 100644 --- a/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs +++ b/9.0/Apps/WhatToEat/src/WhatToEat/ViewModels/SearchResultDetailViewModel.cs @@ -1,4 +1,4 @@ -using System.Windows.Input; +using System.Windows.Input; using System.Diagnostics; using Recipes.Models; using System.Collections.ObjectModel; @@ -147,9 +147,21 @@ public void LoadHitId(string hitId) OnPropertyChanged(nameof(Hit)); LoadSearchResultDetails(); } - catch (Exception) + catch (ArgumentNullException ex) { - Debug.WriteLine("Failed to Load Hit"); + Debug.WriteLine($"Argument null error loading search result: {ex.Message}"); + } + catch (FormatException ex) + { + Debug.WriteLine($"Format error parsing hit ID: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + Debug.WriteLine($"Invalid operation loading search result: {ex.Message}"); + } + catch (Exception ex) + { + Debug.WriteLine($"Failed to load search result hit: {ex.Message}"); } } diff --git a/9.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs b/9.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs index 9ace2947b..f87839ef6 100644 --- a/9.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs +++ b/9.0/Fundamentals/Shell/Xaminals/Views/CatDetailPage.xaml.cs @@ -1,4 +1,4 @@ -using Xaminals.Data; +using Xaminals.Data; using Xaminals.Models; namespace Xaminals.Views @@ -26,9 +26,17 @@ void LoadAnimal(string name) Animal animal = CatData.Cats.FirstOrDefault(a => a.Name == name); BindingContext = animal; } - catch (Exception) + catch (ArgumentNullException ex) { - Console.WriteLine("Failed to load animal."); + System.Diagnostics.Debug.WriteLine($"Argument null error loading cat: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + System.Diagnostics.Debug.WriteLine($"Invalid operation loading cat: {ex.Message}"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to load cat: {ex.Message}"); } } } diff --git a/9.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs b/9.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs index b64d2f451..d0d9e798a 100644 --- a/9.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs +++ b/9.0/Fundamentals/Shell/Xaminals/Views/DogDetailPage.xaml.cs @@ -1,4 +1,4 @@ -using Xaminals.Data; +using Xaminals.Data; using Xaminals.Models; namespace Xaminals.Views @@ -26,9 +26,17 @@ void LoadAnimal(string name) Animal animal = DogData.Dogs.FirstOrDefault(a => a.Name == name); BindingContext = animal; } - catch (Exception) + catch (ArgumentNullException ex) { - Console.WriteLine("Failed to load animal."); + System.Diagnostics.Debug.WriteLine($"Argument null error loading dog: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + System.Diagnostics.Debug.WriteLine($"Invalid operation loading dog: {ex.Message}"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to load dog: {ex.Message}"); } } } diff --git a/9.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs b/9.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs index 51fe807ad..21fcc732e 100644 --- a/9.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs +++ b/9.0/WebServices/TodoREST/TodoAPI/Controllers/TodoItemsController.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using TodoAPI.Interfaces; using TodoAPI.Models; @@ -54,9 +54,19 @@ public IActionResult Create([FromBody]TodoItem item) } _todoRepository.Insert(item); } - catch (Exception) + catch (ArgumentNullException ex) { - return BadRequest(ErrorCode.CouldNotCreateItem.ToString()); + return BadRequest($"{ErrorCode.CouldNotCreateItem}: {ex.Message}"); + } + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotCreateItem}: {ex.Message}"); + } + catch (Exception ex) + { + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotCreateItem}: An unexpected error occurred"); } return Ok(item); } @@ -79,9 +89,23 @@ public IActionResult Edit([FromBody] TodoItem item) } _todoRepository.Update(item); } - catch (Exception) + catch (ArgumentNullException ex) + { + return BadRequest($"{ErrorCode.CouldNotUpdateItem}: {ex.Message}"); + } + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotUpdateItem}: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + return NotFound($"{ErrorCode.RecordNotFound}: {ex.Message}"); + } + catch (Exception ex) { - return BadRequest(ErrorCode.CouldNotUpdateItem.ToString()); + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotUpdateItem}: An unexpected error occurred"); } return NoContent(); } @@ -100,9 +124,19 @@ public IActionResult Delete(string id) } _todoRepository.Delete(id); } - catch (Exception) + catch (ArgumentException ex) + { + return BadRequest($"{ErrorCode.CouldNotDeleteItem}: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + return NotFound($"{ErrorCode.RecordNotFound}: {ex.Message}"); + } + catch (Exception ex) { - return BadRequest(ErrorCode.CouldNotDeleteItem.ToString()); + // Log the exception here in production + return StatusCode(StatusCodes.Status500InternalServerError, + $"{ErrorCode.CouldNotDeleteItem}: An unexpected error occurred"); } return NoContent(); } diff --git a/9.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs b/9.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs index 7e7b6d544..8d62353d6 100644 --- a/9.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs +++ b/9.0/WebServices/TodoREST/TodoAPI/Services/TodoRepository.cs @@ -1,4 +1,4 @@ -using TodoAPI.Interfaces; +using TodoAPI.Interfaces; using TodoAPI.Models; namespace TodoAPI.Services @@ -29,20 +29,59 @@ public TodoItem Find(string id) public void Insert(TodoItem item) { + if (item == null) + { + throw new ArgumentNullException(nameof(item), "TodoItem cannot be null"); + } + + if (string.IsNullOrWhiteSpace(item.ID)) + { + throw new ArgumentException("TodoItem ID cannot be null or empty", nameof(item)); + } + _todoList.Add(item); } public void Update(TodoItem item) { + if (item == null) + { + throw new ArgumentNullException(nameof(item), "TodoItem cannot be null"); + } + + if (string.IsNullOrWhiteSpace(item.ID)) + { + throw new ArgumentException("TodoItem ID cannot be null or empty", nameof(item)); + } + var todoItem = this.Find(item.ID); + if (todoItem == null) + { + throw new InvalidOperationException($"TodoItem with ID '{item.ID}' not found"); + } + var index = _todoList.IndexOf(todoItem); - _todoList.RemoveAt(index); - _todoList.Insert(index, item); + if (index >= 0) + { + _todoList.RemoveAt(index); + _todoList.Insert(index, item); + } } public void Delete(string id) { - _todoList.Remove(this.Find(id)); + if (string.IsNullOrWhiteSpace(id)) + { + throw new ArgumentException("ID cannot be null or empty", nameof(id)); + } + + var todoItem = this.Find(id); + if (todoItem == null) + { + throw new InvalidOperationException($"TodoItem with ID '{id}' not found"); + } + + _todoList.Remove(todoItem); } private void InitializeData()