Copied to clipboard

Flag this post as spam?

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


  • jacob phillips 130 posts 372 karma points
    Jun 05, 2013 @ 01:32
    jacob phillips
    0

    /base, DateFolders package, simple "Create" method

    So in my old umbraco installation 4.0.4.2, I wrote some simple methods and batch scripts to create pages, set all their attributes (picture, teaser text, date, etc.) every night at midnight for staff. This was handy because some people at my company have to create pages every single day and it is a very mundane process for them.  It all worked fine. Specifically, after setting a displayDate property on the document, the "AutoFolders" package correctly created the date folders and published the document, making it immediately available on the web. 

    Now, after upgrading the Server hardware, OS and Database server and Umbraco version (4.9.1) I am bringing all the automation back online, but I am running into a problem with the /base requests. I should mention that I switched from "AutoFolders" package to "DateFolders" package since the latter is built on .NET 4 and the former .NET 3.5

    Now however, when my /base request executes, everything works except that the date folders created by the DateFolders package are unpublished and I get a generic error ( This is strange because when creating an item in the backoffice manually, the DateFolders are always published after creating the item. But when the same type document is created using /base, ONLY the child document gets published.

    If I try to create a document that DateFolders is NOT configured to create folders for, everything works fine.

    However, if I set displayDate and try to publish a document using /base, then I just get a generic "Internal Server 500" error with nothing in the Windows Application Log. I do get this in the Umbraco Log:

    1404848    0   0   2013-06-04 16:21:02.847 Error   Couldn't find any page with the nodeId = 0. This is most likely caused by the page isn't published!  Parameter name: nodeId
    1404849 0 0 2013-06-04 16:21:02.847 Error Couldn't find any page with the nodeId = 0. This is most likely caused by the page isn't published! Parameter name: nodeId
    1404850 0 0 2013-06-04 16:21:02.847 Error Couldn't find any page with the nodeId = 0. This is most likely caused by the page isn't published! Parameter name: nodeId
    1404847 0 4282 2013-06-04 16:21:02.673 Publish
    1404846 0 -1 2013-06-04 16:21:02.083 System Loading content from disk cache...
    1404845 0 4285 2013-06-04 16:21:01.910 New
    1404844 0 4284 2013-06-04 16:21:01.647 New
    1404843 0 4283 2013-06-04 16:21:01.287 New
    1404842 0 4282 2013-06-04 16:21:00.913 Publish
    1404840 0 4282 2013-06-04 16:21:00.630 New

     

    Here is my base method:

            public static string Create(int parentid, string name, string year, string month, string day)
    {

    //since using Date Folders package instead of Auto Folders, the systemDateFolders are being created with /base calls,
    //but not published, So...they have to created manually

    DocumentType dt = DocumentType.GetByAlias("show");
    Document d = Document.MakeNew(name, dt, new umbraco.BusinessLogic.User(0), parentid);
    var displayDate = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day));
    //to modify the document properties....
    d.getProperty("displayDate").Value = displayDate;

    d.Publish(new umbraco.BusinessLogic.User(0));
    d.Save();
    umbraco.library.UpdateDocumentCache(d.Id);



    Document DayFolderParent = new Document(d.ParentId);
    DayFolderParent.Publish(new umbraco.BusinessLogic.User(0));
    DayFolderParent.Save();
    umbraco.library.UpdateDocumentCache(DayFolderParent.Id);



    return d.Id.ToString();

     

    I tried to change the method above so that AFTER I create my page, I get the parentId and then send it a publish, save, and update document cache, like this:

    public static string Create(int parentid, string name, string year, string month, string day){


    //since using Date Folders package instead of Auto Folders, the systemDateFolders are being created with /base calls,
    //but not published, So...they have to created manually

    DocumentType dt = DocumentType.GetByAlias("show");
    Document d = Document.MakeNew(name, dt, new umbraco.BusinessLogic.User(0), parentid);
    var displayDate = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day));
    //to modify the document properties....
    d.getProperty("displayDate").Value = displayDate;

    d.Publish(new umbraco.BusinessLogic.User(0));
    d.Save();
    umbraco.library.UpdateDocumentCache(d.Id);


    //try and get parent folder of newly created document and publish it
    Document DayFolderParent = new Document(d.ParentId);
    DayFolderParent.Publish(new umbraco.BusinessLogic.User(0));
    DayFolderParent.Save();
    umbraco.library.UpdateDocumentCache(DayFolderParent.Id);

    //it doesn't work, no error

    return d.Id.ToString();
    }

    Still nothing.

    The only thing I can think of is that I will have to alter the Create method above to check for the existence of the year date folder first and then create and publish it if it is not already there, then check the month, then the day, then finally create my item. What a hassle, I'd rather not have to do that. Is there something simple I'm just missing? 

     

     

     

     

  • jacob phillips 130 posts 372 karma points
    Jun 05, 2013 @ 05:42
    jacob phillips
    0

    Update.

    I thought to look at the source for the DateFolders package and I noticed that in the New document event that the date's are being set using datetime.now when  creating the date folders:

           /// 
    /// New document event
    ///
    ///The document
    ///The event args
    void Document_New(Document doc, NewEventArgs e)
    {
    try
    {
    DocumentType folderDocType = DocumentType.GetByAlias(_dateFolderDocType);
    if (folderDocType != null)
    {
    Document parent = new Document(doc.ParentId);

    if (_itemDocType.Contains(doc.ContentType.Alias))
    {
    // Date item created
    DateTime now = DateTime.Now;

    Document yearFolder = parent.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Year.ToString());
    if (yearFolder == null)
    {
    // Create year folder
    yearFolder = Document.MakeNew(now.Year.ToString(), DocumentType.GetByAlias(_dateFolderDocType), doc.User, parent.Id);
    }

    Document monthFolder = yearFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Month.ToString("00"));
    if (monthFolder == null)
    {
    // Create month folder
    monthFolder = Document.MakeNew(now.Month.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, yearFolder.Id);
    }

    Document dayFolder = null;
    if (_createDayFolders)
    {
    dayFolder = monthFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Day.ToString("00"));
    if (dayFolder == null)
    {
    // Create day folder
    dayFolder = Document.MakeNew(now.Day.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, monthFolder.Id);
    }
    }

    if (_createDayFolders)
    doc.Move(dayFolder.Id);
    else
    doc.Move(monthFolder.Id);
    doc.Save();

    if (yearFolder != null)
    yearFolder.SaveAndPublish();
    if (monthFolder != null)
    monthFolder.SaveAndPublish();
    if (dayFolder != null)
    dayFolder.SaveAndPublish();

    // Order
    OrderChildrenByName(new Document(parent.Id));
    OrderChildrenByName(new Document(yearFolder.Id));
    if (_createDayFolders)
    OrderChildrenByName(new Document(monthFolder.Id));
    }
    }
    else
    {
    // Date folder doctype is null
    if (BasePage.Current != null)
    BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Date folder property", string.Format("The date folder doctype does not exist ({0})", _dateFolderDocType));
    }
    }
    catch { }
    }

     

    In my base class, I'm trying to set the displayDate before I publish the node. I also realized that when publishing in the backoffice, you always have to create the node first before you can access it's displayDate and change it. So I thought, change your base class to publish/save/updateDocCache the node first, then set the displayDate and publish/save/updateDocCache again.

    The good news is that when I check the back office, the node is created and moved and it's date folders are published. The bad news is that I still get a 500-Internal server error and so the nodeId is not being returned to the whatever the calling function is (in this case a script that makes the base request needs the nodeId for other stuff). No event, nothing negative in umbracoLog. It shows the node and date folders being created with no issues.

    Almost there.....

    Here's the edited class:

                //since using Date Folders package instead of Auto Folders, the systemDateFolders are being created with /base calls, 
    //but not published, So...they have to created manually

    DocumentType dt = DocumentType.GetByAlias("show");
    Document d = Document.MakeNew(name, dt, new umbraco.BusinessLogic.User(0), parentid);
    var displayDate = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day));


    d.Publish(new umbraco.BusinessLogic.User(0));
    d.Save();
    umbraco.library.UpdateDocumentCache(d.Id);

    //now it is published, modify it's properties

    // Get the document by its ID
    Document mdoc = new Document(d.Id);


    //to modify the document properties....
    mdoc.getProperty("displayDate").Value = displayDate;

    // After modifying the document, prepare it for publishing
    mdoc.Publish(new umbraco.BusinessLogic.User(0));
    mdoc.Save();

    // Tell umbraco to publish the document so the updated properties are visible on website
    umbraco.library.UpdateDocumentCache(mdoc.Id);

    return mdoc.Id.ToString();

     

     

  • jacob phillips 130 posts 372 karma points
    Jun 07, 2013 @ 00:30
    jacob phillips
    0

    Ok, so I tried breaking up the method into to two parts. One method handls the create. The next one changes the displayDate. 

    The first one works, the second one gives me the error (but the node is still moved).

    Maybe I should switch to the auto hook up style of base classes?

    No, that didn't work.

    How about trying to pass back the exception through the base request?

     

            [RestExtensionMethod(returnXml = false)]
    public static string GoodBye(int nodeid, int year, int month, int day, int hour, int minute, int second)
    {
    // Get the document by its ID

    string result = "1";

    try
    {

    Document mdoc = new Document(nodeid);

    //var displayDate = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day), hour, minute, second);
    var displayDate = new DateTime(year, month, day, hour, minute, second);


    //to modify the document properties....
    mdoc.getProperty("displayDate").Value = displayDate;

    // After modifying the document, prepare it for publishing
    mdoc.Publish(new umbraco.BusinessLogic.User(0));
    mdoc.Save();

    // Tell umbraco to publish the document so the updated properties are visible on website
    umbraco.library.UpdateDocumentCache(mdoc.Id);
    }
    catch(Exception e)
    {
    result = e.StackTrace.ToString() + "<br /><br />" + e.Message;

    }

    return result;

     

    Ok, that gets me past the generic internal server error; at least now I know which method in the DateFolders package is throwing the error.

    at InfoCaster.Umbraco.Common.DateFolders.Document_AfterSave(Document doc, SaveEventArgs e)
       at umbraco.cms.businesslogic.web.Document.SaveEventHandler.Invoke(Document sender, SaveEventArgs e)
       at umbraco.cms.businesslogic.web.Document.FireAfterSave(SaveEventArgs e)
       at umbraco.cms.businesslogic.web.Document.Save()
       at BaseTest.TestClass.GoodBye(Int32 nodeid, Int32 year, Int32 month, Int32 day, Int32 hour, Int32 minute, Int32 second)

    Object reference not set to an instance of an object.

     

    ...and here is that method, Document_AfterSave(Document doc, SaveEventArgs e)

     

           /// <summary>
    /// After save event
    /// </summary>
    /// <param name="doc">The document</param>
    /// <param name="e">The event args</param>
    void Document_AfterSave(Document doc, SaveEventArgs e)
    {
    if (_itemDocType.Contains(doc.ContentType.Alias))
    {
    DocumentType folderDocType = DocumentType.GetByAlias(_dateFolderDocType);
    if (folderDocType != null)
    {
    if (doc.ParentId > 0)
    {
    // Date item saved
    DateTime date = default(DateTime);
    if (!string.IsNullOrEmpty(_itemDateProperty))
    {
    string dateValue = doc.GetDatePropertyValue(_itemDateProperty);
    if (!string.IsNullOrEmpty(dateValue))
    DateTime.TryParse(dateValue, out date);
    }
    if (date == default(DateTime))
    date = doc.CreateDateTime;

    Document parent, monthFolder, yearFolder, dayFolder = null, dayDoc = null, monthDoc = null, yearDoc = null;

    if (_createDayFolders)
    {
    dayFolder = new Document(doc.ParentId);
    monthFolder = new Document(dayFolder.ParentId);
    yearFolder = new Document(monthFolder.ParentId);
    }
    else
    {
    monthFolder = new Document(doc.ParentId);
    yearFolder = new Document(monthFolder.ParentId);
    }
    parent = new Document(yearFolder.ParentId);

    bool yearChanged, monthChanged, dayChanged = false;
    yearChanged = date.Year.ToString() != yearFolder.Text;
    monthChanged = date.Month.ToString("00") != monthFolder.Text;
    if (_createDayFolders)
    dayChanged = date.Day.ToString("00") != dayFolder.Text;

    if (yearChanged || monthChanged || dayChanged)
    {
    // Date changed
    Document newYearFolder = null, newMonthFolder = null, newDayFolder = null;
    if (yearChanged)
    {
    // Year changed
    newYearFolder = parent.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Year.ToString());
    if (newYearFolder == null)
    {
    // Create year folder
    newYearFolder = Document.MakeNew(date.Year.ToString(), DocumentType.GetByAlias(_dateFolderDocType), doc.User, parent.Id);
    }
    }
    else
    newYearFolder = yearFolder;

    // Month
    newMonthFolder = newYearFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Month.ToString("00"));
    if (newMonthFolder == null)
    {
    // Create month folder
    newMonthFolder = Document.MakeNew(date.Month.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, newYearFolder.Id);
    }

    if (_createDayFolders)
    {
    // Day
    newDayFolder = newMonthFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Day.ToString("00"));
    if (newDayFolder == null)
    {
    // Create day folder
    newDayFolder = Document.MakeNew(date.Day.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, newMonthFolder.Id);
    }
    }

    // Move
    if (_createDayFolders)
    doc.Move(newDayFolder.Id);
    else
    doc.Move(newMonthFolder.Id);

    if (doc.Published)
    doc.SaveAndPublish();

    int orderParentId = newMonthFolder.Id;
    if (_createDayFolders)
    orderParentId = newDayFolder.Id;

    if (!string.IsNullOrEmpty(_itemDateProperty))
    OrderChildrenByDateProperty(new Document(orderParentId), _itemDateProperty);
    else
    OrderChildrenByCreateDate(new Document(orderParentId));

    if (newYearFolder != null)
    newYearFolder.SaveAndPublish();
    if (newMonthFolder != null)
    newMonthFolder.SaveAndPublish();
    if (newDayFolder != null)
    newDayFolder.SaveAndPublish();

    // Delete if empty
    if (_createDayFolders)
    {
    dayDoc = new Document(dayFolder.Id);
    if (dayDoc.ChildCount < 1)
    {
    dayDoc.DeleteCompletely();
    }
    }

    monthDoc = new Document(monthFolder.Id);
    if (monthDoc.ChildCount < 1)
    {
    monthDoc.DeleteCompletely();

    yearDoc = new Document(yearFolder.Id);
    if (yearDoc.ChildCount < 1)
    yearDoc.DeleteCompletely();
    }

    // Order
    OrderChildrenByName(new Document(parent.Id));
    OrderChildrenByName(new Document(newYearFolder.Id));
    if (_createDayFolders)
    OrderChildrenByName(new Document(newMonthFolder.Id));

    doc = new Document(doc.Id);

    BasePage.Current.ClientTools
    .ChangeContentFrameUrl(string.Concat("editContent.aspx?id=", doc.Id));
    }
    }
    else
    {
    // Item is created under 'Content' root, which is unsupported
    if (BasePage.Current != null)
    BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Unsupported", "Creating a datefolders item under 'Content' root is unsupported");
    }
    }
    else
    {
    // Date folder doctype is null
    if (BasePage.Current != null)
    BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Configuration error", string.Format("The date folder doctype ('{0}') does not exist", _dateFolderDocType));
    }
    }
    }

     

    Not that good at C#....I'm not seeing the answer. Is there any change I can make to how I'm setting the displayDate property in my "GoodBye" method  to  not cause this error. I'm not sure where the "Object Not Set" error is coming from in the above  DateFolders method....

  • jacob phillips 130 posts 372 karma points
    Jun 07, 2013 @ 02:14
    jacob phillips
    0

    Ok, I guess I'll just catch the error being thrown on .Save() and move on:

    Here is the thread on the DateFolder package Bug List

Please Sign in or register to post replies

Write your reply to:

Draft