public static IUiControl Render(
            string consoleId,
            string elementProviderName,
            FlowToken flowToken,
            FormFlowUiDefinition formFlowUiCommand,
            IFormChannelIdentifier channel,
            bool debugMode,
            FlowControllerServicesContainer servicesContainer)
        {
            FlowControllerServicesContainer formServicesContainer = new FlowControllerServicesContainer(servicesContainer);
            formServicesContainer.AddService(new FormFlowRenderingService());
            formServicesContainer.AddService(new FormFlowWebRenderingService());

            IFormMarkupProvider formMarkupProvider = formFlowUiCommand.MarkupProvider;
            IFormMarkupProvider customToolbarItemsMarkupProvider = formFlowUiCommand.CustomToolbarItemsMarkupProvider;
            Dictionary<string, object> innerFormBindings = formFlowUiCommand.BindingsProvider.GetBindings();
            Dictionary<IFormEventIdentifier, FormFlowEventHandler> eventHandlers = formFlowUiCommand.EventHandlers;
            Dictionary<string, List<ClientValidationRule>> bindingsValidationRules = formFlowUiCommand.BindingsValidationRules;

            FormTreeCompiler formCompiler = new FormTreeCompiler();
            IUiContainer renderingContainer = GetRenderingContainer(channel, formFlowUiCommand.UiContainerType);

            // Setting state related objects so the delegate below can access them "fresh"
            CurrentFormTreeCompiler = formCompiler;
            CurrentInnerFormBindings = innerFormBindings;
            CurrentControlContainer = (IWebUiContainer)renderingContainer;


            Dictionary<string, object> containerEventHandlerStubs = new Dictionary<string, object>();

            foreach (IFormEventIdentifier eventIdentifier in eventHandlers.Keys)
            {
                IFormEventIdentifier localScopeEventIdentifier = eventIdentifier;  // See: Local variable usage with anonymous methods within loop control structures

                EventHandler handlerStub = delegate(object sender, EventArgs e)
                {
                    try
                    {
                        BaseEventHandler(consoleId, elementProviderName, flowToken, formFlowUiCommand, servicesContainer, eventHandlers, localScopeEventIdentifier, formServicesContainer);
                    }
                    catch (Exception ex)
                    {
                        formServicesContainer.GetService<IManagementConsoleMessageService>().ShowLogEntry(typeof(FormFlowUiDefinitionRenderer), ex);
                        throw;
                    }
                };

                containerEventHandlerStubs.Add(eventIdentifier.BindingName, handlerStub);

                if (innerFormBindings.ContainsKey(eventIdentifier.BindingName))
                {
                    innerFormBindings.Remove(eventIdentifier.BindingName);
                }

                innerFormBindings.Add(eventIdentifier.BindingName, handlerStub);
            }

            XDocument document;

            using (XmlReader formMarkupReader = formMarkupProvider.GetReader())
            {
                document = XDocument.Load(formMarkupReader);
                formMarkupReader.Close();
            }

            formCompiler.Compile(document, channel, innerFormBindings, debugMode, "", bindingsValidationRules);

            IUiControl innerForm = formCompiler.UiControl;

            IUiControl customToolbarItems = null;
            if (customToolbarItemsMarkupProvider != null)
            {
                FormTreeCompiler toolbarCompiler = new FormTreeCompiler();
                using (XmlReader formMarkupReader = customToolbarItemsMarkupProvider.GetReader())
                {
                    toolbarCompiler.Compile(formMarkupReader, channel, innerFormBindings, debugMode, bindingsValidationRules);
                }
                customToolbarItems = toolbarCompiler.UiControl;
            }

            CurrentControlTreeRoot = (IWebUiControl)innerForm;

            string label = formCompiler.Label;
            if(label.IsNullOrEmpty())
            {
                label = formFlowUiCommand.ContainerLabel ?? "";
            }

            string labelField = GetFormLabelField(document);
            ResourceHandle containerIcon = formCompiler.Icon;

            return renderingContainer.Render(formCompiler.UiControl, customToolbarItems, channel, containerEventHandlerStubs, label, labelField, containerIcon);
        }
        public IFlowUiDefinition GetCurrentUiDefinition(FlowToken flowToken)
        {
            WorkflowFlowToken workflowFlowToken = (WorkflowFlowToken)flowToken;

            if (!WorkflowFacade.WorkflowExists(workflowFlowToken.WorkflowInstanceId))
            {
                Log.LogVerbose(LogTitle, "The workflow with Id = {0} does not exists", workflowFlowToken.WorkflowInstanceId);
                return null;
            }


            using (GlobalInitializerFacade.CoreNotLockedScope)
            {
                Semaphore semaphore = WorkflowFacade.WaitForIdleStatus(workflowFlowToken.WorkflowInstanceId);
                if (semaphore != null)
                {
                    Log.LogVerbose(LogTitle, "The workflow with Id = {0} is running, waiting until its done.", workflowFlowToken.WorkflowInstanceId);

                    semaphore.WaitOne(TimeSpan.FromSeconds(10), true);

                    Log.LogVerbose(LogTitle, "Done waiting on the workflow with Id = {0}.", workflowFlowToken.WorkflowInstanceId);
                }
            }


            FormData formFunction = WorkflowFacade.GetFormData(workflowFlowToken.WorkflowInstanceId);
            if (formFunction == null)
            {
                return null;
            }

            FormFlowUiDefinition formFlowUiDefinition;
            if (formFunction.FormDefinition != null)
            {
                formFlowUiDefinition = new FormFlowUiDefinition(
                           new XmlTextReader(new StringReader(formFunction.FormDefinition)),
                           formFunction.ContainerType,
                           formFunction.ContainerLabel,
                           formFunction.Bindings,
                           formFunction.BindingsValidationRules
                    );
            }
            else if (formFunction.FormMarkupProvider != null)
            {
                formFlowUiDefinition = new FormFlowUiDefinition(
                           formFunction.FormMarkupProvider,
                           formFunction.ContainerType,
                           formFunction.ContainerLabel,
                           formFunction.Bindings,
                           formFunction.BindingsValidationRules
                    );
            }
            else
            {
                throw new NotImplementedException();
            }

            if (!string.IsNullOrEmpty(formFunction.CustomToolbarDefinition))
            {
                formFlowUiDefinition.SetCustomToolbarMarkupProvider(new XmlTextReader(new StringReader(formFunction.CustomToolbarDefinition)));
            }
            else if (formFunction.CustomToolbarMarkupProvider != null)
            {
                formFlowUiDefinition.SetCustomToolbarMarkupProvider(formFunction.CustomToolbarMarkupProvider);
            }


            AddEventHandles(formFlowUiDefinition, workflowFlowToken.WorkflowInstanceId);

            return formFlowUiDefinition;
        }
        private static void BaseEventHandler(string consoleId, 
                                             string elementProviderName, 
                                             FlowToken flowToken,
                                             FormFlowUiDefinition formFlowUiCommand,
                                             FlowControllerServicesContainer servicesContainer, 
                                             Dictionary<IFormEventIdentifier, FormFlowEventHandler> eventHandlers,
                                             IFormEventIdentifier localScopeEventIdentifier,
                                             FlowControllerServicesContainer formServicesContainer)
        {
            FormTreeCompiler activeFormTreeCompiler = CurrentFormTreeCompiler;
            Dictionary<string, object> activeInnerFormBindings = CurrentInnerFormBindings;

            FormFlowEventHandler handler = eventHandlers[localScopeEventIdentifier];
            Dictionary<string, Exception> bindingErrors = activeFormTreeCompiler.SaveAndValidateControlProperties();

            formServicesContainer.AddService(new BindingValidationService(bindingErrors));

            handler.Invoke(flowToken, activeInnerFormBindings, formServicesContainer);

            if (formServicesContainer.GetService<IManagementConsoleMessageService>().CloseCurrentViewRequested)
            {
                ViewTransitionHelper.HandleCloseCurrentView(formFlowUiCommand.UiContainerType);
                return;
            }
            
            var formFlowService = (FormFlowRenderingService) formServicesContainer.GetService<IFormFlowRenderingService>();
            bool replacePageOutput = (formServicesContainer.GetService<IFormFlowWebRenderingService>().NewPageOutput != null);

            bool rerenderView = formFlowService.RerenderViewRequested;
            if (formFlowService.BindingPathedMessages != null)
            {
                ShowFieldMessages(CurrentControlTreeRoot, formFlowService.BindingPathedMessages, CurrentControlContainer,
                                    servicesContainer);
            }

            List<bool> boolCounterList = new List<bool> {replacePageOutput, rerenderView};

            if (boolCounterList.Count(f => f) > 1)
            {
                StringBuilder sb = new StringBuilder("Flow returned conflicting directives for post handling:\n");
                if (replacePageOutput) sb.AppendLine(" - Replace page output with new web control.");
                if (rerenderView) sb.AppendLine(" - Rerender view.");

                throw new InvalidOperationException(sb.ToString());
            }

            if (rerenderView)
            {
                Log.LogVerbose("FormFlowRendering", "Re-render requested");
                IFlowUiDefinition newFlowUiDefinition = FlowControllerFacade.GetCurrentUiDefinition(flowToken,
                                                                                                    servicesContainer);
                if (!(newFlowUiDefinition is FlowUiDefinitionBase))
                    throw new NotImplementedException("Unable to handle transitions to ui definition of type " +
                                                        newFlowUiDefinition.GetType());
                ViewTransitionHelper.HandleRerender(consoleId, elementProviderName, flowToken, formFlowUiCommand,
                                                    (FlowUiDefinitionBase) newFlowUiDefinition, servicesContainer);
            }

            if (replacePageOutput)
            {
                Log.LogVerbose("FormFlowRendering", "Replace pageoutput requested");
                IFormFlowWebRenderingService webRenderingService =
                    formServicesContainer.GetService<IFormFlowWebRenderingService>();
                Control newPageOutput = webRenderingService.NewPageOutput;

                foreach (Control control in GetNestedControls(newPageOutput).Where(f => f is ScriptManager).ToList())
                {
                    control.Parent.Controls.Remove(control);
                }

                Page currentPage = HttpContext.Current.Handler as Page;

                HtmlHead newHeadControl = GetNestedControls(newPageOutput).FirstOrDefault(f => f is HtmlHead) as HtmlHead;

                HtmlHead oldHeadControl = currentPage.Header;

                ControlCollection headContainer = null;
                bool headersHasToBeSwitched = newHeadControl != null && oldHeadControl != null;
                if (headersHasToBeSwitched)
                {
                    headContainer = newHeadControl.Parent.Controls;
                    headContainer.Remove(newHeadControl);
                }

                currentPage.Controls.Clear();
                if (string.IsNullOrEmpty(webRenderingService.NewPageMimeType))
                {
                    currentPage.Response.ContentType = "text/html";
                }
                else
                {
                    currentPage.Response.ContentType = webRenderingService.NewPageMimeType;
                }
                currentPage.Controls.Add(newPageOutput);

                if (headersHasToBeSwitched)
                {
                    oldHeadControl.Controls.Clear();
                    oldHeadControl.InnerHtml = "";
                    oldHeadControl.InnerText = "";
                    if (newHeadControl.ID != null)
                    {
                        oldHeadControl.ID = newHeadControl.ID;
                    }
                    oldHeadControl.Title = newHeadControl.Title;

                    headContainer.AddAt(0, oldHeadControl);

                    foreach (Control c in newHeadControl.Controls.Cast<Control>().ToList())
                    {
                        oldHeadControl.Controls.Add(c);
                    }
                }
            }
            
        }
        private static void AddEventHandles(FormFlowUiDefinition formFlowUiDefinition, Guid instanceId)
        {
            IEnumerable<string> eventNames = WorkflowFacade.GetCurrentFormEvents(instanceId);

            FormData formData = WorkflowFacade.GetFormData(instanceId);

            foreach (string eventName in eventNames)
            {
                if (formData != null && formData.ExcludedEvents != null && formData.ExcludedEvents.Contains(eventName)) continue;

                switch (eventName)
                {
                    case "Save":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Save, OnSave);
                        break;

                    case "SaveAndPublish":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.SaveAndPublish, OnSaveAndPublish);
                        break;

                    case "Next":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Next, OnNext);
                        break;

                    case "Previous":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Previous, OnPrevious);
                        break;

                    case "Finish":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Finish, OnFinish);
                        break;

                    case "Cancel":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Cancel, OnCancel);
                        break;

                    case "Preview":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Preview, OnPreview);
                        break;

                    case "CustomEvent01":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent01, OnCustomEvent01);
                        break;

                    case "CustomEvent02":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent02, OnCustomEvent02);
                        break;

                    case "CustomEvent03":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent03, OnCustomEvent03);
                        break;

                    case "CustomEvent04":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent04, OnCustomEvent04);
                        break;

                    case "CustomEvent05":
                        formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent05, OnCustomEvent05);
                        break;
                }
            }

            IEventHandleFilter eventHandlerFilter = WorkflowFacade.GetEventHandleFilter(instanceId);
            if (eventHandlerFilter != null)
            {
                eventHandlerFilter.Filter(formFlowUiDefinition.EventHandlers);
            }
        }