Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • QuasPie 25 posts 85 karma points
    Aug 28, 2013 @ 16:29
    QuasPie
    0

    Workflow for updating existing document by ID

    Hi there!

    I'm trying to make a custom workflow for contour.

    The Workflow succeeds in getting some data from the formular, saving the value in a property-field picked in the workflow and saving the document specified by ID in the forumular.

    The Workflow fails, however, to actually publish the document.

    Here's my code for publishing (I've tried a lot of other snippets for this):

    Document d = new Document(root);
    d.Save();
    d.Publish(d.User);
    umbraco.library.UpdateDocumentCache(d.Id);
    

    Some of this I got from a video by Niels at umbraco.tv.

    By entire workflow c# file looks like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using umbraco.BusinessLogic;
    using umbraco.cms.businesslogic.web;
    using umbraco.cms.businesslogic.propertytype;
    using umbraco.cms.businesslogic.property;
    using Umbraco.Forms.Data;
    using Umbraco.Forms.Core;
    using Umbraco.Forms.Core.Enums;
    
    namespace AttackMonkey.Contour.WorkFlows
    {
        public class PublishFormAsPage : WorkflowType
        {
    
            public PublishFormAsPage()
            {
                this.Id = new Guid("139c868c-9bfc-41ae-85ff-cc22af63abfc");
                this.Name = "Save as umbraco document - parent page from form";
                this.Description = "Saves the form values as an umbraco document node with a specific type, with the parent page being selected from the form itself, rather than being a fixed node.";
            }
    
            [Umbraco.Forms.Core.Attributes.Setting("Document Type", description = "Map document type", control = "Umbraco.Forms.Core.FieldSetting.DocumentMapper")]
            public string Fields { get; set; }
    
            [Umbraco.Forms.Core.Attributes.Setting("Publish", description = "Publish document instantly", control = "Umbraco.Forms.Core.FieldSetting.Checkbox")]
            public string Publish { get; set; }
    
            [Umbraco.Forms.Core.Attributes.Setting("Field containing node id", description = "The field in the form that contains the node id of the page to save to", control = "Umbraco.Forms.Core.FieldSetting.FieldPicker")]
            public string RootNode { get; set; }
    
    
            public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
            {
                Dictionary<string, string> mappings = new Dictionary<string, string>();
                int dtId = 0;
                int root = -1;
    
                //old code to get node id
                //int.TryParse(RootNode, out root);
    
                //new code, using the field mapping from the settings, gets the value of the field specified as containing the page id
                if (record.RecordFields.ContainsKey(new Guid(RootNode)))
                {
                    int.TryParse(record.RecordFields[new Guid(RootNode)].ValuesAsString(), out root);
                }
    
                if (root == 0)
                    root = -1;
    
                string nameMapping = "NodeName";
    
                string[] array = Fields.Trim().Split('|');
    
                foreach (string s in array)
                {
                    string[] a = s.Trim().Split(',');
    
                    if (a.Count() == 1 && s.Trim().Length >= 4)
                    {
    
                        if (dtId == 0)
                            int.TryParse(s.Trim(), out dtId);
    
                    }
                    else if (a.Count() == 3)
                    {
    
                        string mapping = "";
    
                        if (!string.IsNullOrEmpty(a[2]))
                            mapping = record.RecordFields[new Guid(a[2])].ValuesAsString();
                        else if (!string.IsNullOrEmpty(a[1]))
                            mapping = Umbraco.Forms.Core.Services.WorkflowService.parseAttribute(e.Context, record, a[1]);
    
                        if ((!string.IsNullOrEmpty(mapping)))
                        {
                            if (a[0] == "__nodeName")
                                nameMapping = mapping;
                            else
                            {
                                mappings.Add(a[0], mapping);
                                LogHelper.Debug(a[0] + " " + mapping);
                            }
                        }
                    }
                }
    
                DocumentType dt = new DocumentType(dtId);
    
                if (dt != null)
                {
                    ////ensure that the question used in the url isn't stupidly long by limiting the name mapping to the first sentence
                    //if (nameMapping.Contains("."))
                    //{
                    //    nameMapping = nameMapping.Substring(0, nameMapping.IndexOf("."));
                    //}
    
                    Document d = new Document(root);
    
                    foreach (Property p in d.getProperties)
                    {
    
                        try
                        {
    
                            if (mappings.ContainsKey(p.PropertyType.Alias))
                            {
                                p.Value = mappings[p.PropertyType.Alias];
                            }
    
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Debug(ex.ToString());
                        }
                    }
    
                    //d.Save();
    
                    /*if (Publish == true.ToString())
                    {
                        d.Publish(User.GetUser(0));
                        umbraco.library.PublishSingleNode(d.Id);
                    }*/
    
                    d.Save();
                    d.Publish(d.User);
                    umbraco.library.UpdateDocumentCache(d.Id);
                }
                return WorkflowExecutionStatus.Completed;
            }
    
            public override List<Exception> ValidateSettings()
            {
                return new List<Exception>();
            }
        }
    }
    

    The code is mainly built on the PublishFormAsPage workflow and partially on other different workflows i found.

    What the * am I doing wrong?!

  • Comment author was deleted

    Aug 29, 2013 @ 10:12

    Hmm code looks ok, have you tried debugging the code to see if it actually reaches the publish method

  • Comment author was deleted

    Aug 29, 2013 @ 10:12

    And nothing hooked to the publish event that might prevent the publish? Is the parent page published ?

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 10:44
    QuasPie
    0

    Well.. I've tried making a workflow that has no dynamic variables passing a value into the document and publishing it. It still won't publish correctly.

    The thing is, that the value I post is saved to the document by what i must assume is the...

    d.Save();
    

    ...method. And since the submit method comes first thing after, I assume it reaches the method correct.

    The parrent-page is published, as are all ancestors.

    We seem to have the same problem when trying to publish using a 3rd party control-application calling the same API.

    We're trying this on Umbraco 6.1.4 with contour 3.0.9

  • Comment author was deleted

    Aug 29, 2013 @ 11:07

    Hmm might be a bug then, mind switching to the new API's in v6 for some details check

    http://umbraco.com/follow-us/blog-archive/2013/1/22/introducing-contentservice-aka-the-v6-api.aspx

    Should be an easy update

  • Comment author was deleted

    Aug 29, 2013 @ 11:11

    Will check if the default save as umbraco document workflow still works since that also uses the old api

  • Comment author was deleted

    Aug 29, 2013 @ 11:37

    That still works so must be something in the code then

    Can you also check if you can get the default save as umbraco document workflow publishing a doc?

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 11:50
    QuasPie
    0

    I'll just look into that API update and get back in a moment.

    You mean the workflow using the "SaveAsUmbracoNode.cs"? If so, the document I'm trying to publish is actually generated by that workflow. This works fine.

    This, however, uses a slight different code for publishing:

     d.Save();
    
                    if (Publish == true.ToString()) {
                        d.Publish(new umbraco.BusinessLogic.User(0));
                        umbraco.library.UpdateDocumentCache(d.Id);
                    }
    

    But i've tried this too.

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 12:06
    QuasPie
    0

    You mean something like this?

    Document d = new Document(root);
                    var contentService = Services.ContentService;
    
                    foreach (Property p in d.getProperties)
                    {
    
                        try
                        {
    
                            if (mappings.ContainsKey(p.PropertyType.Alias))
                            {
                                product.SetValue(p.PropertyType.Alias, mappings);
                            }
    
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Debug(ex.ToString());
                        }
                    }
    
    
                    d.Save();
                    contentService.SaveAndPublish(d);
                    umbraco.library.UpdateDocumentCache(d.Id);
    
  • Comment author was deleted

    Aug 29, 2013 @ 12:50

    Yeah but if the default workflow works it isn't a bug in the api , does publishing from the backoffice work on the doc that you are trying to publish from code?

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 13:13
    QuasPie
    0

    Oh ok :)

    Well.. If i open the document in the backend and publish it, it works. If I right-click the document and choose publish it just keeps loading and loading and never publish it.

  • Comment author was deleted

    Aug 29, 2013 @ 13:14

    Anything in the umbraco log files?

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 13:15
    QuasPie
    0

    If however the document is published and I republish it by right-clicking, it also works.

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 13:30
    QuasPie
    0

    Well well, this might be interesting! There are a lot of dictionary-failures in the traceLog, but this particular element grapped my attention.

    2013-08-29 13:23:02,970 [47] WARN Umbraco.Web.Routing.NiceUrlProvider - [Thread 12] Couldn't find any page with nodeId=-1. This is most likely caused by the page not being published.

    This might also be interesting...

    2013-08-29 13:21:44,845 [47] INFO umbraco.BusinessLogic.Log - [Thread 14] Redirected log call (please use Umbraco.Core.Logging.LogHelper instead of umbraco.BusinessLogic.Log) | Type: Error | User: 0 | NodeId: -1 | Comment: SEOChecker error in PageNotFound Module: System.Threading.ThreadAbortException: Thread was being aborted. at System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End() at SEOChecker.HttpModules.UrlModule.(Object , EventArgs )

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 13:33
    QuasPie
    0

    Dont know if NesletterStudio might have anything to do with it.. but:

    2013-08-29 13:30:39,786 [47] WARN Umbraco.Web.Routing.NiceUrlProvider - [Thread 76] Couldn't find any page with nodeId=-1. This is most likely caused by the page not being published. 2013-08-29 13:30:47,087 [47] INFO umbraco.presentation.publishingService - [Thread 37] newsletterstudioBounces has been called with response: False 2013-08-29 13:30:56,447 [47] WARN Umbraco.Web.Dictionary.DefaultCultureDictionary - [Thread 75] Error returning dictionary item 'Submit'. Exception: System.ArgumentException: No key Submit exists in dictionary

  • Comment author was deleted

    Aug 29, 2013 @ 13:52

    Errors don't seem related

  • Comment author was deleted

    Aug 29, 2013 @ 13:52

    Mind sending the code file I can give it a try then?

  • Comment author was deleted

    Aug 29, 2013 @ 13:57

    Sharing it here would do the trick https://gist.github.com/ :)

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 14:05
    QuasPie
    0

    Uhm.. yeah no problem :) I guess I posted it right, never used gist though :p

    https://gist.github.com/anonymous/6414475100ad107d66eb

  • Comment author was deleted

    Aug 29, 2013 @ 14:21

    Thanks, will give it a try, yeah it's just easier to copy it from there then on this forum :)

  • Comment author was deleted

    Aug 29, 2013 @ 14:38

    Hmm publish seems to work but it's silently failing in setting the property values ...

  • Comment author was deleted

    Aug 29, 2013 @ 14:58

    Can you confirm that the property values do update in your case?

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 15:28
    QuasPie
    0

    When i fill out the form and thereby activate the workflow, it saves the correct value into the document. It just won't show on the site. Also I get this yellow star beside the document in the backend. Like this:

    showing that the image is not published

    But the value saves correctly, like this:

    The value turns out right

  • QuasPie 25 posts 85 karma points
    Aug 29, 2013 @ 15:32
    QuasPie
    0

    The code in the front-end form looks like this:

    enter image description here

    And the entry like this:

    enter image description here

  • Comment author was deleted

    Aug 30, 2013 @ 10:11

    Can't reproduce this one :( maybe try using the new api to publish the doc and see if that has any difference?

  • QuasPie 25 posts 85 karma points
    Aug 30, 2013 @ 13:59
    QuasPie
    0

    I would, but I can't call the Services namespace from my workflow...

    Is it possible that you could provide me with a working workflow using the new API?

  • Comment author was deleted

    Aug 30, 2013 @ 14:17

    Here is a console app that uses the new API so should give you details in how to access the services https://github.com/sitereactor/umbraco-console-example/blob/master/UmbConsole/Program.cs

  • QuasPie 25 posts 85 karma points
    Aug 30, 2013 @ 14:43
    QuasPie
    0

    Seems to be the using Umbraco.Core.Persistence; NS i was missing. This seems to work, I'll just test it and get back to you :)

  • QuasPie 25 posts 85 karma points
    Aug 30, 2013 @ 15:13
    QuasPie
    0

    Now I'm able to publish the document :) I'll merge the code and post the solution workflow here :)

    Thank you very much for your time (y)

  • QuasPie 25 posts 85 karma points
    Aug 30, 2013 @ 15:52
    QuasPie
    101

    Aight! If anyone in the future stumbles upon this, heres the solution. (There might be a way to merge the two workflows, but I'm not going to do that).

    The first workflow is to save the new values to the document.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using umbraco.BusinessLogic;
    using umbraco.cms.businesslogic.web;
    using umbraco.cms.businesslogic.propertytype;
    using umbraco.cms.businesslogic.property;
    
    using Umbraco.Forms.Data;
    using Umbraco.Forms.Core;
    using Umbraco.Forms.Core.Enums;
    
    namespace AttackMonkey.Contour.WorkFlows
    {
        public class PublishFormAsPage : WorkflowType
        {
    
            public PublishFormAsPage()
            {
                this.Id = new Guid("139c868c-9bfc-41ae-85ff-cc22af63abfc");
                this.Name = "Save as umbraco document - parent page from form";
                this.Description = "Saves the form values as an umbraco document node with a specific type, with the parent page being selected from the form itself, rather than being a fixed node.";
            }
    
            [Umbraco.Forms.Core.Attributes.Setting("Document Type", description = "Map document type", control = "Umbraco.Forms.Core.FieldSetting.DocumentMapper")]
            public string Fields { get; set; }
    
            [Umbraco.Forms.Core.Attributes.Setting("Publish", description = "Publish document instantly", control = "Umbraco.Forms.Core.FieldSetting.Checkbox")]
            public string Publish { get; set; }
    
            [Umbraco.Forms.Core.Attributes.Setting("Field containing node id", description = "The field in the form that contains the node id of the page to save to", control = "Umbraco.Forms.Core.FieldSetting.FieldPicker")]
            public string RootNode { get; set; }
    
    
            public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
            {
                Dictionary<string, string> mappings = new Dictionary<string, string>();
                int dtId = 0;
                int root = -1;
    
                if (record.RecordFields.ContainsKey(new Guid(RootNode)))
                {
                    int.TryParse(record.RecordFields[new Guid(RootNode)].ValuesAsString(), out root);
                }
    
                if (root == 0)
                    root = -1;
    
                string nameMapping = "NodeName";
    
                string[] array = Fields.Trim().Split('|');
    
                foreach (string s in array)
                {
                    string[] a = s.Trim().Split(',');
    
                    if (a.Count() == 1 && s.Trim().Length >= 4)
                    {
    
                        if (dtId == 0)
                            int.TryParse(s.Trim(), out dtId);
    
                    }
                    else if (a.Count() == 3)
                    {
    
                        string mapping = "";
    
                        if (!string.IsNullOrEmpty(a[2]))
                            mapping = record.RecordFields[new Guid(a[2])].ValuesAsString();
                        else if (!string.IsNullOrEmpty(a[1]))
                            mapping = Umbraco.Forms.Core.Services.WorkflowService.parseAttribute(e.Context, record, a[1]);
    
                        if ((!string.IsNullOrEmpty(mapping)))
                        {
                            if (a[0] == "__nodeName")
                                nameMapping = mapping;
                            else
                            {
                                mappings.Add(a[0], mapping);
                                LogHelper.Debug(a[0] + " " + mapping);
                            }
                        }
                    }
                }
    
                DocumentType dt = new DocumentType(dtId);
    
                if (dt != null)
                {
    
                    Document d = new Document(root);
    
                    foreach (Property p in d.getProperties)
                    {
    
                        try
                        {
    
                            if (mappings.ContainsKey(p.PropertyType.Alias))
                            {
                                p.Value = mappings[p.PropertyType.Alias];
                            }
    
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Debug(ex.ToString());
                        }
                    }
    
                    d.Save();
    
                }
                return WorkflowExecutionStatus.Completed;
            }
    
            public override List<Exception> ValidateSettings()
            {
                return new List<Exception>();
            }
        }
    }
    

    The next workflow is to publish the document after it's saved. The workflows also has to be put in this order, when you add them to the form in contour.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    
    using umbraco.BusinessLogic;
    using umbraco.cms.businesslogic.web;
    /*using umbraco.cms.businesslogic.propertytype;
    using umbraco.cms.businesslogic.property;*/
    
    using Umbraco.Forms.Data;
    using Umbraco.Forms.Core;
    using Umbraco.Forms.Core.Enums;
    
    using Umbraco.Core;
    using Umbraco.Core.Persistence;
    using Umbraco.Core.Services;
    
    namespace testNewApi.Contour.WorkFlows
    {
        public class testNewApi : WorkflowType
        {
    
            public testNewApi()
            {
                this.Id = new Guid("746f927c-9cfd-10ea-98ba-aa67aa89cdee");
                this.Name = "Publish document";
                this.Description = "This needs no description!";
            }
    
            [Umbraco.Forms.Core.Attributes.Setting("Node ID", description = "*The ID of the document to publish", control = "Umbraco.Forms.Core.FieldSetting.TextField")]
            public string NodeID { get; set; }
    
    
            public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
            {
                var context = ApplicationContext.Current; 
                var serviceContext = context.Services;
                var contentService = serviceContext.ContentService;
    
                int docID = Convert.ToInt32(NodeID);
                var doc = contentService.GetById(docID);
    
                contentService.SaveAndPublish(doc);
    
                return WorkflowExecutionStatus.Completed;
            }
    
            public override List<Exception> ValidateSettings()
            {
                return new List<Exception>();
            }
        }
    }
    

    I hope someone might put this into good use!

  • Comment author was deleted

    Aug 30, 2013 @ 15:53

    Ah sweet glad that one does the trick :)

Please Sign in or register to post replies

Write your reply to:

Draft