diff --git a/src/core/Elsa.Abstractions/Models/Workflow.cs b/src/core/Elsa.Abstractions/Models/Workflow.cs index 3d8753a79..40c528cc1 100644 --- a/src/core/Elsa.Abstractions/Models/Workflow.cs +++ b/src/core/Elsa.Abstractions/Models/Workflow.cs @@ -23,14 +23,11 @@ namespace Elsa.Models Metadata = new WorkflowMetadata(); } - [JsonConverter(typeof(StringEnumConverter))] public WorkflowStatus Status { get; set; } - public Instant CreatedAt { get; set; } public Instant? StartedAt { get; set; } public Instant? HaltedAt { get; set; } public Instant? FinishedAt { get; set; } - public IList Activities { get; set; } = new List(); public IList Connections { get; set; } = new List(); public Stack Scopes { get; set; } diff --git a/src/core/Elsa.Core/Serialization/Tokenizers/WorkflowTokenizer.cs b/src/core/Elsa.Core/Serialization/Tokenizers/WorkflowTokenizer.cs index 2f01eaa2c..bba8232a0 100644 --- a/src/core/Elsa.Core/Serialization/Tokenizers/WorkflowTokenizer.cs +++ b/src/core/Elsa.Core/Serialization/Tokenizers/WorkflowTokenizer.cs @@ -7,9 +7,11 @@ using Elsa.Activities; using Elsa.Extensions; using Elsa.Models; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using NodaTime; +using NodaTime.Extensions; using NodaTime.Serialization.JsonNet; namespace Elsa.Serialization.Tokenizers @@ -18,19 +20,23 @@ namespace Elsa.Serialization.Tokenizers { private readonly ITokenizerInvoker tokenizerInvoker; private readonly IActivityLibrary activityLibrary; + private readonly IClock clock; private readonly JsonSerializer jsonSerializer; - public WorkflowTokenizer(ITokenizerInvoker tokenizerInvoker, IActivityLibrary activityLibrary) + public WorkflowTokenizer(ITokenizerInvoker tokenizerInvoker, IActivityLibrary activityLibrary, IClock clock) { this.tokenizerInvoker = tokenizerInvoker; this.activityLibrary = activityLibrary; - - jsonSerializer = JsonSerializer.Create( - new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver() - } - .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)); + this.clock = clock; + + var settings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + } + .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); + + settings.Converters.Add(new StringEnumConverter()); + jsonSerializer = JsonSerializer.Create(settings); } public async Task TokenizeWorkflowAsync(Workflow value, CancellationToken cancellationToken) @@ -48,11 +54,15 @@ namespace Elsa.Serialization.Tokenizers { { "metadata", JToken.FromObject(workflow.Metadata, jsonSerializer) }, { "status", workflow.Status.ToString() }, + { "createdAt", SerializeInstant(workflow.CreatedAt) }, + { "startedAt", SerializeInstant(workflow.StartedAt) }, + { "finishedAt", SerializeInstant(workflow.FinishedAt) }, + { "haltedAt", SerializeInstant(workflow.HaltedAt) }, { "activities", await SerializeActivitiesAsync(context, cancellationToken) }, { "connections", SerializeConnections(context, workflow) }, { "haltedActivities", SerializeHaltedActivities(context, workflow) }, { "scopes", SerializeScopes(context, scopeIdLookup) }, - { "currentScope", SerializeCurrentScope(workflow, scopeIdLookup) } + { "currentScope", SerializeCurrentScope(workflow, scopeIdLookup) }, }; return token; @@ -72,6 +82,10 @@ namespace Elsa.Serialization.Tokenizers { Metadata = token["metadata"].ToObject(jsonSerializer), Status = (WorkflowStatus) Enum.Parse(typeof(WorkflowStatus), token["status"].Value()), + CreatedAt = DeserializeInstant(token["createdAt"]) ?? clock.GetCurrentInstant(), + StartedAt = DeserializeInstant(token["startedAt"]), + FinishedAt = DeserializeInstant(token["finishedAt"]), + HaltedAt = DeserializeInstant(token["haltedAt"]), Activities = activityDictionary.Values.ToList(), Connections = DeserializeConnections(token, activityDictionary).ToList(), BlockingActivities = DeserializeHaltedActivities(token, activityDictionary).ToList(), @@ -263,6 +277,16 @@ namespace Elsa.Serialization.Tokenizers return dictionary; } + + private Instant? DeserializeInstant(JToken token) + { + return token?.ToObject(jsonSerializer)?.ToInstant(); + } + + private JToken SerializeInstant(Instant? value) + { + return value != null ? JToken.FromObject(value.Value, jsonSerializer) : null; + } private Task GetActivityDescriptorAsync(string activityName, CancellationToken cancellationToken) { diff --git a/src/samples/SampleHost.Web/appsettings.json b/src/samples/SampleHost.Web/appsettings.json index 773b4d1fb..1c853c66c 100644 --- a/src/samples/SampleHost.Web/appsettings.json +++ b/src/samples/SampleHost.Web/appsettings.json @@ -6,7 +6,7 @@ }, "AllowedHosts": "*", "FileStore": { - "RootDirectory": "C:\\Activities\\Projects\\Elsa\\src\\samples\\SampleDashboard.Web\\App_Data\\Sites\\Default\\elsa\\workflows", + "RootDirectory": "C:\\Activities\\Projects\\Elsa\\src\\samples\\SampleDashboard.Web\\App_Data\\Sites\\Default\\workflows", "Format": "YAML" } }