From 5ce9465f25393b325a9dc7df8ca3b3cf3f79b3ba Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 24 Apr 2011 12:08:28 +0100 Subject: [PATCH] Show better error messages in the Add Package Reference dialog when an aggregate exception has an inner aggregate exception. --- .../Project/PackageManagement.csproj | 1 + .../Src/AggregateExceptionErrorMessage.cs | 43 ++++++++++++++++++ .../Project/Src/PackagesViewModel.cs | 13 +++--- .../Test/Src/PackagesViewModelTests.cs | 45 +++++++++++++++++++ 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/AggregateExceptionErrorMessage.cs diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index 49222a3ffe..b6b8fd233e 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -67,6 +67,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/AggregateExceptionErrorMessage.cs b/src/AddIns/Misc/PackageManagement/Project/Src/AggregateExceptionErrorMessage.cs new file mode 100644 index 0000000000..47f8c4b1f5 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/AggregateExceptionErrorMessage.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace ICSharpCode.PackageManagement +{ + public class AggregateExceptionErrorMessage + { + AggregateException ex; + StringBuilder errorMessage = new StringBuilder(); + + public AggregateExceptionErrorMessage(AggregateException ex) + { + this.ex = ex; + BuildErrorMessage(); + } + + void BuildErrorMessage() + { + BuildErrorMessage(ex.InnerExceptions); + } + + void BuildErrorMessage(IEnumerable exceptions) + { + foreach (Exception ex in exceptions) { + var aggregateEx = ex as AggregateException; + if (aggregateEx != null) { + BuildErrorMessage(aggregateEx.InnerExceptions); + } else { + errorMessage.AppendLine(ex.Message); + } + } + } + + public override string ToString() + { + return errorMessage.ToString().TrimEnd(); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackagesViewModel.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackagesViewModel.cs index 29c9950417..66de9905ef 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackagesViewModel.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackagesViewModel.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; +using System.Text; using System.Windows.Input; + using NuGet; namespace ICSharpCode.PackageManagement @@ -127,16 +129,17 @@ namespace ICSharpCode.PackageManagement base.OnPropertyChanged(null); } - protected void SaveError(AggregateException ex) + void SaveError(AggregateException ex) { - SaveError(ex.InnerException); + HasError = true; + ErrorMessage = GetErrorMessage(ex); ICSharpCode.Core.LoggingService.Debug(ex); } - protected void SaveError(Exception ex) + string GetErrorMessage(AggregateException ex) { - HasError = true; - ErrorMessage = ex.Message; + var errorMessage = new AggregateExceptionErrorMessage(ex); + return errorMessage.ToString(); } void UpdatePackagesForSelectedPage(PackagesForSelectedPageResult result) diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackagesViewModelTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackagesViewModelTests.cs index 5f49cd78c4..2313d52f67 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackagesViewModelTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackagesViewModelTests.cs @@ -1080,6 +1080,51 @@ namespace PackageManagement.Tests Assert.AreEqual("Test", viewModel.ErrorMessage); } + [Test] + public void ErrorMessage_BackgroundTaskHasAggregateExceptionWithNestedInnerAggregateException_ErrorMessageTakenFromInnerException() + { + CreateViewModel(); + viewModel.AddSixFakePackages(); + viewModel.ReadPackages(); + + Exception innerEx1 = new Exception("Test1"); + Exception innerEx2 = new Exception("Test2"); + AggregateException innerAggregateEx = new AggregateException(innerEx1, innerEx2); + AggregateException aggregateEx = new AggregateException(innerAggregateEx); + taskFactory.FirstFakeTaskCreated.Exception = aggregateEx; + taskFactory.FirstFakeTaskCreated.IsFaulted = true; + CompleteReadPackagesTask(); + + string expectedErrorMessage = + "Test1\r\n" + + "Test2"; + + Assert.AreEqual(expectedErrorMessage, viewModel.ErrorMessage); + } + + [Test] + public void ErrorMessage_BackgroundTaskHasAggregateExceptionWithTwoInnerExceptionsWhenItFinishes_ErrorMessageTakenFromAllInnerExceptions() + { + CreateViewModel(); + viewModel.AddSixFakePackages(); + viewModel.ReadPackages(); + + Exception innerEx1 = new Exception("Test1"); + Exception innerEx2 = new Exception("Test2"); + Exception innerEx3 = new Exception("Test3"); + AggregateException aggregateEx = new AggregateException(innerEx1, innerEx2, innerEx3); + taskFactory.FirstFakeTaskCreated.Exception = aggregateEx; + taskFactory.FirstFakeTaskCreated.IsFaulted = true; + CompleteReadPackagesTask(); + + string expectedErrorMessage = + "Test1\r\n" + + "Test2\r\n" + + "Test3"; + + Assert.AreEqual(expectedErrorMessage, viewModel.ErrorMessage); + } + [Test] public void HasError_ErrorMessageDisplayedAndReadPackagesRetriedAfterFailure_ReturnsFalse() {