OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.43k stars 2.4k forks source link

[Workflows] invalidoperationexception: operation is not valid due to the current state of the object. #14653

Open weirdyang opened 1 year ago

weirdyang commented 1 year ago

Describe the bug

To Reproduce

Steps to reproduce the behavior:

  1. set a workflow context property to a string array
  2. navigate to the workflow index
  3. this error is thrown sometimes
  4. Issue is resolved once I restart the project
invalidoperationexception: operation is not valid due to the current state of the object. system.reflection.runtimemethodinfo.getgenericmethoddefinition() yessql.services.defaultquery.convertfragment(istringbuilder builder, expression expression) 

I am setting a property on the workflow context to log any expressions which evaluates to null, I am testing with a sqlite database. code in the custom IWorkflowExpressionEvaluator

        public async Task<T> EvaluateAsync<T>(
            WorkflowExpression<T> expression, 
            WorkflowExecutionContext workflowContext, 
            TextEncoder encoder)
        {
            var templateContext = new TemplateContext(_templateOptions);
            var expressionContext = new WorkflowExecutionExpressionContext(templateContext, workflowContext);

            await _workflowContextHandlers.InvokeAsync((h, expressionContext) => h.EvaluatingExpressionAsync(expressionContext), expressionContext, _logger);

            // Set WorkflowContext as a local scope property.
            var result = await _liquidTemplateManager.RenderStringAsync(
                expression.Expression,
                encoder ?? NullEncoder.Default,
                new Dictionary<string, FluidValue>() { ["Workflow"] = new ObjectValue(workflowContext) }
                );
            if(string.IsNullOrWhiteSpace(result) || result.Equals("null", StringComparison.InvariantCultureIgnoreCase))
            {
                if(expression.Expression is not null)
                {
                    LogErrorMessage(
                        string.Format("{0} evaluates to null", expression.Expression), 
                        workflowContext);
                }
                return default;
            }
            return (T)Convert.ChangeType(result, typeof(T));
        }
        private void LogErrorMessage(string message, WorkflowExecutionContext context) 
        {
            if(context.Properties.ContainsKey(NullExpressionPropertyName))
            {
                var listOfNull = context.Properties[NullExpressionPropertyName] as string[];
                if(listOfNull != null)
                {
                    listOfNull = listOfNull.Append(message).ToArray();
                    context.Properties[NullExpressionPropertyName] = listOfNull;
                }
            } else
            {
                context.Properties[NullExpressionPropertyName] = new string[] { message };
            }
        }

Expected behavior

To be able to navigate to the workflow type index

sebastienros commented 1 year ago

set a workflow context property to a string array

I assume that the thing it can't handle, arrays. Thanks for the repro.