private static WorkflowRuntime InitWorkflowRuntime() { var runtime = DWKitRuntime.CreateWorkflowRuntime() .WithActionProvider(new ActionProvider()) .WithRuleProvider(new RuleProvider()) .WithTimerManager(new TimerManager()); runtime.OnWorkflowError += (sender, args) => { if (Debugger.IsAttached) { var info = ExceptionUtils.GetExceptionInfo(args.Exception); var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("Workflow engine. An exception occurred while the process was running."); errorBuilder.AppendLine($"ProcessId: {args.ProcessInstance.ProcessId}"); errorBuilder.AppendLine($"ExecutedTransition: {args.ExecutedTransition?.Name}"); errorBuilder.AppendLine($"Message: {info.Message}"); errorBuilder.AppendLine($"Exceptions: {info.Exeptions}"); errorBuilder.Append($"StackTrace: {info.StackTrace}"); Debug.WriteLine(errorBuilder); } //TODO Add exceptions logging here }; //events subscription runtime.ProcessActivityChanged += (sender, args) => { ActivityChanged(args, runtime).Wait(); }; runtime.ProcessStatusChanged += (sender, args) => { }; //TODO If you have planned to use Code Actions functionality that required references to external assemblies you have to register them here //runtime.RegisterAssemblyForCodeActions(Assembly.GetAssembly(typeof(SomeTypeFromMyAssembly))); //starts the WorkflowRuntime //TODO If you have planned use Timers the best way to start WorkflowRuntime is somwhere outside of this function in Global.asax for example runtime.Start(); return(runtime); }
public static void Configure(IHttpContextAccessor httpContextAccessor, IConfigurationRoot configuration, string connectionstringName = "default") { #region License var licensefile = "license.key"; if (File.Exists(licensefile)) { try { var licenseText = File.ReadAllText(licensefile); DWKitRuntime.RegisterLicense(licenseText); } catch { //TODO add write to log } } #endregion #if (DEBUG) DWKitRuntime.UseMetadataCache = false; //CodeActionsCompiller.DebugMode = true; #elif (RELEASE) DWKitRuntime.UseMetadataCache = true; #endif DWKitRuntime.ConnectionStringData = configuration[$"ConnectionStrings:{connectionstringName}"]; DWKitRuntime.DbProvider = AutoDetectProvider(); DWKitRuntime.Security = new SecurityProvider(httpContextAccessor); DWKitRuntime.Metadata = new DefaultMetadataProvider("Metadata/metadata.json", "Metadata/Forms", "Metadata/Localization"); if (configuration["DWKit:BlockMetadataChanges"] == "True") { DWKitRuntime.Metadata.BlockMetadataChanges = true; } CodeActionsCompiller.RegisterAssembly(typeof(WorkflowRuntime).Assembly); DWKitRuntime.CompileAllCodeActionsAsync().Wait(); //It is necessery to have this assembly for compile code with dynamic CodeActionsCompiller.RegisterAssembly(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); DWKitRuntime.ServerActions.RegisterUsersProvider("filters", new Filters()); DWKitRuntime.ServerActions.RegisterUsersProvider("triggers", new Triggers()); //Initial inbox/outbox notifiers DWKitRuntime.AddClientNotifier(typeof(ClientNotificationHub), ClientNotifiers.NotifyClientsAboutInboxStatus); //Initial document count notifier DWKitRuntime.AddClientNotifier(typeof(ClientNotificationHub), SideMenuInitialNotifier); //User group classifier for notifications DWKitRuntime.SignalRGroupClassifier = SignalRGroupClassifier; //Documents count change on Insert new document or update document DynamicEntityOperationNotifier.SubscribeToInsertByTableName("Document", "SideMenuNotification", (m, c) => { Func <Task> func = async() => { await NotifyDocumentCountChange(m, c, false); }; func.FireAndForgetWithDefaultExceptionLogger(); }); DynamicEntityOperationNotifier.SubscribeToUpdateByTableName("Document", "SideMenuNotification", (m, c) => { Func <Task> func = async() => { await NotifyDocumentCountChange(m, c, true); }; func.FireAndForgetWithDefaultExceptionLogger(); }); //Documents count change and inbox outbox change on document deletions DynamicEntityOperationNotifier.SubscribeToDeleteByTableName("Document", "SideMenuNotification", (m, c) => { Func <Task> func = async() => { await ClientNotifiers.DeleteWokflowAndNotifyClients(m, c); await NotifyDocumentCountChange(m, c, false); }; func.FireAndForgetWithDefaultExceptionLogger(); }); var runtime = WorkflowInit.Runtime; }
private static WorkflowRuntime InitWorkflowRuntime() { var runtime = DWKitRuntime.CreateWorkflowRuntime() .WithActionProvider(ActionProvider ?? new WorkflowActions()) .WithRuleProvider(RuleProvider ?? new RuleProvider()) .WithExternalParametersProvider(ExternalParametersProvider ?? new WorkflowParameters()) .AsSingleServer(); runtime.WithPlugin(new FilePlugin()); runtime.WithPlugin(new LoopPlugin()); if (CodeAutocompleteProvider != null) { runtime.CodeAutocompleteProvider = CodeAutocompleteProvider; } //events subscription //runtime.ProcessActivityChanged += (sender, args) => { }; //runtime.ProcessStatusChanged += (sender, args) => { }; runtime.OnWorkflowError += (sender, args) => { var isTimerTriggeredTransitionChain = !string.IsNullOrEmpty(args.ProcessInstance.ExecutedTimer) || //for timers executed from main branch (args.ProcessInstance.MergedSubprocessParameters != null && //for timers executed from subprocess !string.IsNullOrEmpty(args.ProcessInstance.MergedSubprocessParameters.GetParameter(DefaultDefinitions.ParameterExecutedTimer.Name)?.Value?.ToString())); if (isTimerTriggeredTransitionChain) { args.SuppressThrow = true; //prevent unhandled exception in a thread } var info = ExceptionUtils.GetExceptionInfo(args.Exception); var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("Workflow engine. An exception occurred while the process was running."); errorBuilder.AppendLine($"ProcessId: {args.ProcessInstance.ProcessId}"); errorBuilder.AppendLine($"ExecutedTransition: {args.ExecutedTransition?.Name}"); errorBuilder.AppendLine($"Message: {info.Message}"); errorBuilder.AppendLine($"Exceptions: {info.Exeptions}"); errorBuilder.Append($"StackTrace: {info.StackTrace}"); if (Debugger.IsAttached) { Debug.WriteLine(errorBuilder); } else { //TODO Add exceptions logging here Console.WriteLine(errorBuilder); } }; //It is necessery to have this assembly for compile code with dynamic runtime.RegisterAssemblyForCodeActions(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly, true); //TODO If you have planned to use Code Actions functionality that required references to external assemblies you have to register them here //runtime.RegisterAssemblyForCodeActions(Assembly.GetAssembly(typeof(SomeTypeFromMyAssembly))); runtime.RegisterAssemblyForCodeActions(Assembly.GetAssembly(typeof(DynamicEntity))); //starts the WorkflowRuntime //TODO If you have planned use Timers the best way to start WorkflowRuntime is somewhere outside of this function in Global.asax for example runtime.Start(); return(runtime); }
private static void Configure(ISecurityProvider security, IConfigurationRoot configuration, string connectionstringName = "default") { #region License var licensefile = "license.key"; if (File.Exists(licensefile)) { try { var licenseText = File.ReadAllText(licensefile); DWKitRuntime.RegisterLicense(licenseText); } catch { //TODO add write to log } } #endregion #if (DEBUG) DWKitRuntime.UseMetadataCache = false; //CodeActionsCompiler.DebugMode = true; #elif (RELEASE) DWKitRuntime.UseMetadataCache = true; #endif DWKitRuntime.ConnectionStringData = configuration[$"ConnectionStrings:{connectionstringName}"]; DWKitRuntime.DbProvider = AutoDetectProvider(); DWKitRuntime.Security = security; var path = configuration["Metadata:path"]; if (string.IsNullOrEmpty(path)) { path = "Metadata/metadata.json"; } DWKitRuntime.Metadata = new DefaultMetadataProvider(path, "Metadata/Forms", "Metadata/Localization"); if (configuration["DWKit:BlockMetadataChanges"] == "True") { DWKitRuntime.Metadata.BlockMetadataChanges = true; } if (configuration["DWKit:BlockMetadataChanges"] == "True") { DWKitRuntime.Metadata.BlockMetadataChanges = true; DWKitRuntime.Metadata.ResourceFolder = configuration["DWKit:ResourceFolder"]; } if (!string.IsNullOrWhiteSpace(configuration["DWKit:CodeActionsDebugMode"])) { DWKitRuntime.CodeActionsDebugMode = bool.Parse(configuration["DWKit:CodeActionsDebugMode"]); } CodeActionsCompiler.RegisterAssembly(typeof(WorkflowRuntime).Assembly); //It is necessary to have this assembly for compile code with dynamic CodeActionsCompiler.RegisterAssembly(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); DWKitRuntime.CompileAllCodeActionsAsync().Wait(); DWKitRuntime.ServerActions.RegisterUsersProvider("filters", new Filters()); DWKitRuntime.ServerActions.RegisterUsersProvider("triggers", new Triggers()); //Forcing the creation of a WF runtime to initialize timers and the Flow. try { WorkflowInit.ForceInit(); } catch (Exception e) { if (Debugger.IsAttached) { var info = ExceptionUtils.GetExceptionInfo(e); var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("Workflow engine start failed."); errorBuilder.AppendLine($"Message: {info.Message}"); errorBuilder.AppendLine($"Exceptions: {info.Exeptions}"); errorBuilder.Append($"StackTrace: {info.StackTrace}"); Debug.WriteLine(errorBuilder); } } }
public static async Task NotifyDocumentCountChange(EntityModel model, List <ChangeOperation> changes, bool isUpdate) { //Wide View All notification if (!isUpdate) { await SendNotificationToViewAllGroup(model); } var ids = new List <string>(); foreach (var changeOperation in changes) { if (!isUpdate) { if (model.Attributes.Any(a => a.Name.Equals("AuthorId", StringComparison.Ordinal))) { var item = changeOperation.Entity["AuthorId"]?.ToString(); if (item != null) { ids.Add(item); } } if (model.Attributes.Any(a => a.Name.Equals("EmployeeId", StringComparison.Ordinal))) { var item = changeOperation.Entity["EmployeeId"]?.ToString(); if (item != null) { ids.Add(item); } } if (model.Attributes.Any(a => a.Name.Equals("Employees", StringComparison.Ordinal))) { var employeesStr = changeOperation.Entity["Employees"]?.ToString(); if (employeesStr != null) { var employeeIds = JsonConvert.DeserializeObject <List <string> >(employeesStr); ids.AddRange(employeeIds); } } } else { AddUsersFromChangeOperation(changeOperation, "AuthorId", ids); AddUsersFromChangeOperation(changeOperation, "EmployeeId", ids); AddUsersFromChangeOperation(changeOperation, "Employees", ids, true); } } ids = ids.Distinct().ToList(); foreach (var userId in ids) { var userChange = new Dictionary <string, long>(); if (!DWKitRuntime.Security.CheckPermission(new Guid(userId), "Documents", "ViewAll")) { userChange.Add(model.Name.ToLower(), await Document.GetDocumentTypeCountAsync(model.SourceDataModelName, Document.GetViewFilterForUser(new Guid(userId), model))); await DWKitRuntime.SendStateChangeToUserAsync(userId, SideMenuPath, userChange); } } }
public static void Configure(IHttpContextAccessor httpContextAccessor, IConfigurationRoot configuration, string connectionstringName = "default") { #region License var licensefile = "license.key"; if (File.Exists(licensefile)) { try { var licenseText = File.ReadAllText(licensefile); DWKitRuntime.RegisterLicense(licenseText); } catch { //TODO add write to log } } #endregion #if (DEBUG) DWKitRuntime.UseMetadataCache = false; #elif (RELEASE) DWKitRuntime.UseMetadataCache = true; #endif DWKitRuntime.ConnectionStringData = configuration[$"ConnectionStrings:{connectionstringName}"]; DWKitRuntime.DbProvider = AutoDetectProvider(); DWKitRuntime.Security = new SecurityProvider(httpContextAccessor); var path = configuration["Metadata:path"]; if (string.IsNullOrEmpty(path)) { path = "Metadata/metadata.json"; } DWKitRuntime.Metadata = new DefaultMetadataProvider(path, "Metadata/Forms", "Metadata/Localization"); if (configuration["DWKit:BlockMetadataChanges"] == "True") { DWKitRuntime.Metadata.BlockMetadataChanges = true; } if (!string.IsNullOrWhiteSpace(configuration["DWKit:CodeActionsDebugMode"])) { DWKitRuntime.CodeActionsDebugMode = bool.Parse(configuration["DWKit:CodeActionsDebugMode"]); } CodeActionsCompiler.RegisterAssembly(typeof(WorkflowRuntime).Assembly); //It is necessary to have this assembly for compile code with dynamic CodeActionsCompiler.RegisterAssembly(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); DWKitRuntime.CompileAllCodeActionsAsync().Wait(); DWKitRuntime.ServerActions.RegisterUsersProvider("filters", new Filters()); DWKitRuntime.ServerActions.RegisterUsersProvider("triggers", new Triggers()); //Initial inbox/outbox notifiers DWKitRuntime.AddClientNotifier(typeof(ClientNotificationHub), ClientNotifiers.NotifyClientsAboutInboxStatus); //Remove process after the document was removed DynamicEntityOperationNotifier.SubscribeToDeleteByTableName("Document", "WorkflowDelete", (e, c) => { Func <Task> task = async() => { await ClientNotifiers.DeleteWokflowAndNotifyClients(e, c); }; task.FireAndForgetWithDefaultExceptionLogger(); }); //Forcing the creation of a WF runtime to initialize timers and the Flow. try { WorkflowInit.ForceInit(); } catch (Exception e) { if (Debugger.IsAttached) { var info = ExceptionUtils.GetExceptionInfo(e); var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("Workflow engine start failed."); errorBuilder.AppendLine($"Message: {info.Message}"); errorBuilder.AppendLine($"Exceptions: {info.Exeptions}"); errorBuilder.Append($"StackTrace: {info.StackTrace}"); Debug.WriteLine(errorBuilder); } } }
private static void Configure(ISecurityProvider security, IConfigurationRoot configuration, string connectionstringName = "default", ILogger logger = null) { DWKitRuntime.LicensePath = configuration["DWKit:LicensePath"]; DWKitRuntime.CheckLicense(); #if (DEBUG) DWKitRuntime.UseMetadataCache = false; //CodeActionsCompiler.DebugMode = true; #elif (RELEASE) DWKitRuntime.UseMetadataCache = true; #endif if (!string.IsNullOrWhiteSpace(configuration["DWKit:StoreSchemesInMetadataFolder"])) { DWKitRuntime.StoreSchemesInMetadataFolder = bool.Parse(configuration["DWKit:StoreSchemesInMetadataFolder"]); } DWKitRuntime.ConnectionStringData = configuration[$"ConnectionStrings:{connectionstringName}"]; DWKitRuntime.DbProvider = AutoDetectProvider(configuration, logger); DWKitRuntime.Security = security; DWKitRuntime.QueryInterceptor = GetQueryInterceptor(); var path = configuration["DWKit:MetadataPath"]; string metadataPath = null; if (string.IsNullOrEmpty(path)) { path = "Metadata/metadata.json"; metadataPath = "Metadata"; } else { metadataPath = Path.GetDirectoryName(path); } DWKitRuntime.Metadata = new DefaultMetadataProvider(path, $"{metadataPath}/Forms", $"{metadataPath}/Localization", workflowFolder: $"{metadataPath}/Workflow"); if ("true".Equals(configuration["DWKit:BlockMetadataChanges"], StringComparison.InvariantCultureIgnoreCase)) { DWKitRuntime.Metadata.BlockMetadataChanges = true; } if (!string.IsNullOrWhiteSpace(configuration["DWKit:ResourceFolder"])) { DWKitRuntime.Metadata.ResourceFolder = configuration["DWKit:ResourceFolder"]; } if (!string.IsNullOrWhiteSpace(configuration["DWKit:CodeActionsDebugMode"])) { DWKitRuntime.CodeActionsDebugMode = bool.Parse(configuration["DWKit:CodeActionsDebugMode"]); } CodeActionsCompiler.RegisterAssembly(typeof(WorkflowRuntime).Assembly); //It is necessary to have this assembly for compile code with dynamic CodeActionsCompiler.RegisterAssembly(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly); DWKitRuntime.CompileAllCodeActionsAsync().Wait(); DWKitRuntime.ServerActions.RegisterUsersProvider("filters", new Filters()); DWKitRuntime.ServerActions.RegisterUsersProvider("triggers", new Triggers()); DWKitRuntime.ServerActions.RegisterUsersProvider("actions", new ServerActions()); //Forcing the creation of a WF runtime to initialize timers and the Flow. try { WorkflowInit.ForceInit(); } catch (Exception e) { if (Debugger.IsAttached) { var info = ExceptionUtils.GetExceptionInfo(e); var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("Workflow engine start failed."); errorBuilder.AppendLine($"Message: {info.Message}"); errorBuilder.AppendLine($"Exceptions: {info.Exeptions}"); errorBuilder.Append($"StackTrace: {info.StackTrace}"); Debug.WriteLine(errorBuilder); } } //Init plugins DWKitRuntime.InitPlugins().Wait(); }