From fc954d99687427b28cd9db9e3aa0f85f1d875bce Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 31 Aug 2021 16:09:04 +0200 Subject: [PATCH] Improve error messages Closes #1425 --- .../Middleware/HttpEndpointMiddleware.cs | 3 ++- .../Models/SimpleException.cs | 11 +++++--- .../Models/SimpleExceptionProperty.cs | 14 +++++++++++ .../ExpressionEvaluationException.cs | 25 +++++++++++++++++++ .../Expressions/ExpressionEvaluator.cs | 3 ++- 5 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/core/Elsa.Abstractions/Models/SimpleExceptionProperty.cs create mode 100644 src/core/Elsa.Core/Exceptions/ExpressionEvaluationException.cs diff --git a/src/activities/Elsa.Activities.Http/Middleware/HttpEndpointMiddleware.cs b/src/activities/Elsa.Activities.Http/Middleware/HttpEndpointMiddleware.cs index 9f7628a4b..fea4974f3 100644 --- a/src/activities/Elsa.Activities.Http/Middleware/HttpEndpointMiddleware.cs +++ b/src/activities/Elsa.Activities.Http/Middleware/HttpEndpointMiddleware.cs @@ -128,7 +128,7 @@ namespace Elsa.Activities.Http.Middleware pendingWorkflowInstance = await workflowInstanceStore.FindByIdAsync(pendingWorkflow.WorkflowInstanceId, cancellationToken); if (pendingWorkflowInstance is not null - && pendingWorkflowInstance.WorkflowStatus == Elsa.Models.WorkflowStatus.Faulted + && pendingWorkflowInstance.WorkflowStatus == WorkflowStatus.Faulted && !httpContext.Response.HasStarted) { httpContext.Response.ContentType = "application/json"; @@ -137,6 +137,7 @@ namespace Elsa.Activities.Http.Middleware var faultedResponse = JsonConvert.SerializeObject(new { errorMessage = $"Workflow faulted at {pendingWorkflowInstance.FaultedAt!} with error: {pendingWorkflowInstance.Fault!.Message}", + exception = pendingWorkflowInstance.Fault?.Exception, workflow = new { name = pendingWorkflowInstance.Name, diff --git a/src/core/Elsa.Abstractions/Models/SimpleException.cs b/src/core/Elsa.Abstractions/Models/SimpleException.cs index 44c892fc5..6c96b677b 100644 --- a/src/core/Elsa.Abstractions/Models/SimpleException.cs +++ b/src/core/Elsa.Abstractions/Models/SimpleException.cs @@ -1,28 +1,33 @@ using System; +using System.Collections; +using System.Collections.Generic; namespace Elsa.Models { public class SimpleException { - public SimpleException(Type type, string message, string stackTrace, SimpleException? innerException = default) + public SimpleException(Type type, string message, string stackTrace, IDictionary data, SimpleException? innerException = default) { Type = type; Message = message; StackTrace = stackTrace; InnerException = innerException; + Data = data; } public Type Type { get; set; } public string Message { get; set; } public string StackTrace { get; set; } public SimpleException? InnerException { get; set; } + public IDictionary Data { get; set; } public static SimpleException? FromException(Exception? ex) { if (ex == null) return null; - - var simpleException = new SimpleException(ex.GetType(), ex.Message, ex.StackTrace); + + var exceptionType = ex.GetType(); + var simpleException = new SimpleException(exceptionType, ex.Message, ex.StackTrace, ex.Data); if (ex.InnerException != null) simpleException.InnerException = FromException(ex.InnerException); diff --git a/src/core/Elsa.Abstractions/Models/SimpleExceptionProperty.cs b/src/core/Elsa.Abstractions/Models/SimpleExceptionProperty.cs new file mode 100644 index 000000000..7e626cb1f --- /dev/null +++ b/src/core/Elsa.Abstractions/Models/SimpleExceptionProperty.cs @@ -0,0 +1,14 @@ +namespace Elsa.Models +{ + public class SimpleExceptionProperty + { + public SimpleExceptionProperty(string name, object value) + { + Name = name; + Value = value; + } + + public string Name { get; set; } + public object Value { get; set; } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Exceptions/ExpressionEvaluationException.cs b/src/core/Elsa.Core/Exceptions/ExpressionEvaluationException.cs new file mode 100644 index 000000000..78bda48cc --- /dev/null +++ b/src/core/Elsa.Core/Exceptions/ExpressionEvaluationException.cs @@ -0,0 +1,25 @@ +using System; + +namespace Elsa.Exceptions +{ + public class ExpressionEvaluationException : Exception + { + public string Expression + { + get => (string)Data[nameof(Expression)]; + set => Data[nameof(Expression)] = value; + } + + public string Syntax + { + get => (string)Data[nameof(Syntax)]; + set => Data[nameof(Syntax)] = value; + } + + public ExpressionEvaluationException(string message, string expression, string syntax, Exception innerException) : base(message, innerException) + { + Expression = expression; + Syntax = syntax; + } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Expressions/ExpressionEvaluator.cs b/src/core/Elsa.Core/Expressions/ExpressionEvaluator.cs index 212eba292..0ab2c92a5 100644 --- a/src/core/Elsa.Core/Expressions/ExpressionEvaluator.cs +++ b/src/core/Elsa.Core/Expressions/ExpressionEvaluator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Elsa.Exceptions; using Elsa.Models; using Elsa.Services.Models; using Microsoft.Extensions.Logging; @@ -63,7 +64,7 @@ namespace Elsa.Expressions catch (Exception e) { _logger.LogDebug(e, "Failed to evaluate expression {Expression} using syntax {Syntax}", expression, syntax); - throw; + throw new ExpressionEvaluationException("Failed to evaluate expression", expression, syntax, e); } } }