1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Creating Pages with API - Pages left locked.

Creating Pages with API - Pages left locked.

7 posts, 0 answered
  1. Adam @Habanero
    Adam @Habanero avatar
    45 posts
    Registered:
    22 Jun 2012
    22 May 2008
    Link to this post
    Hi there

    We are implementing a small script that will allow us to create a few hundred pages defined in an XML file using the Sitefinity API.

    I have it working where I can create the pages from the xml, but the pages are left locked by the current user.

    I can call myPage.Staged.Checkin() and it will unlock the page, but this only works after the page is created and some basic properties are set, and not after I've added some controls to the page programatically.

    Here is an example:

    The below works fine, the page is not locked after i'm done.

    //import stores from xml file  
     
            CmsManager manager = new CmsManager();  
     
            //Find the Locations Page  
            ICmsPage locationsPage = null;  
     
            foreach (object page in manager.GetPages())  
            {  
                ICmsPage typedPage = page as ICmsPage;  
                if (typedPage != null && typedPage.Name.ToLower() == "locations")  
                {  
                    locationsPage = typedPage;  
                    break;  
                }  
            }  
     
           Telerik.Cms.Data.PageTemplate template = ((Telerik.Cms.Data.CmsTemplateContent) manager.GetTemplate("StoreTemplate")).PageTemplate;  
     
            ICmsPage storePage = null;  
            if (locationsPage != null)  
            {  
     
     
     
                System.Xml.XmlDocument stores = new System.Xml.XmlDocument();  
     
                stores.Load(Server.MapPath("~/Files/LocationDetails.xml"));  
     
                XmlNode rootnode = stores.DocumentElement;  
                 
                XmlNodeList nodeList = rootnode.SelectNodes("/Locations/Location");  
     
                foreach (XmlNode locNode in nodeList)  
                {  
     
                    XmlNode node;  
     
                    node = locNode.SelectSingleNode("Name");  
     
                    storePage = manager.CreatePage(node.InnerText.Replace(' ', '_'));  
                    storePage.Navigable = true;  
                    storePage.MenuName = node.InnerText;  
                    storePage.ParentID = locationsPage.ID;  
                    storePage.Title = node.InnerText;  
                    storePage.Staged.Template = template;  
                      
     
                    storePage.CheckIn();  
                    storePage.Publish();  
     
                      
                }  
                 
            } 


    If However, I add some controls to the page I get an error when the line storePage.Checkin(); is called.  The error is

    You cannot change a value of an object that is not in transaction.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: Nolics.ORMapper.Base.NolnetException: You cannot change a value of an object that is not in transaction.

    Source Error:

    Line 126:                storePage.Staged.AddControl("StoreImagePlaceHolder", image);
    Line 127:
    Line 128:                storePage.Staged.CheckIn();
    Line 129:                storePage.Publish();
    Line 130:

    Source File: c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs    Line: 128

    Stack Trace:

    [NolnetException: You cannot change a value of an object that is not in transaction.]
       Nolics.ORMapper.Base.OdbClassHelper.CheckAssign(IOdbView clView, String propertyName, Object oldValue, Object newValue) +346
       Telerik.Cms.Data.StagedPage.set_Locked(Boolean value) +109
       Telerik.Cms.Data.StagedPage.CheckIn() +35
       UserControls_TestControl.ImportStoresButton_Click(Object sender, EventArgs e) in c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs:128
       System.Web.UI.WebControls.Button.OnClick(EventArgs e) +131
       System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +39
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3215
    


    If I remove the linke
    storePage.Staged.CheckIn(); then the page saves fine, but it still shows as locked in the sitefinity admin.


    What am I missing?  What is the proper way to do this?

    Thanks

  2. Adam @Habanero
    Adam @Habanero avatar
    45 posts
    Registered:
    22 Jun 2012
    22 May 2008
    Link to this post

    Continuing on with this.

    I've added the following code imeditely before the storePage.Staged.Checkin() line and i'm getting a new error.

    I'm sure I must just be missing some information on how to properly work with these objects.

                    //address  
                      
                    node = locNode.SelectSingleNode("AddressBlock");  
                    XmlNode subNode = node.SelectSingleNode("Address");  
                      
                    LiteralControl lit = new LiteralControl();  
                      
                    lit.Text = "<h2>" + StoreName + "</h2><br>";  
                    lit.Text += subNode.InnerText + "<br>";  
                      
                    subNode = node.SelectSingleNode("City");  
                    lit.Text += subNode.InnerText + ", ";  
                      
                    subNode = node.SelectSingleNode("Province");  
                    lit.Text += subNode.InnerText + " ";  
     
                    subNode = node.SelectSingleNode("PostalCode");  
                    lit.Text += subNode.InnerText;  
     
                    storePage.Staged.AddControl("AddressPlaceHolder", lit); 

    Error is:

     

    Server Error in '/' Application.

    IOdbClass must be joined to a transaction.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidOperationException: IOdbClass must be joined to a transaction.

    Source Error:

    Line 145:                lit.Text += subNode.InnerText;
    Line 146:
    Line 147:                storePage.Staged.AddControl("AddressPlaceHolder", lit);
    Line 148:
    Line 149:                storePage.Staged.CheckIn();

    Source File: c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs    Line: 147

    Stack Trace:

    [InvalidOperationException: IOdbClass must be joined to a transaction.]
       Telerik.Cms.Data.StagedPage.AddControl(String containerId, String name, Control control) +357
       UserControls_TestControl.ImportStoresButton_Click(Object sender, EventArgs e) in c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs:147
       System.Web.UI.WebControls.Button.OnClick(EventArgs e) +131
       System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +39
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3215
    

  3. Georgi
    Georgi avatar
    3583 posts
    Registered:
    28 Oct 2016
    27 May 2008
    Link to this post
    Hello Adam,

    The reason why you get these errors is because in the AddControls() method, we call Commit on the transaction. Further instructions as CheckIn() will fail, because the transaction has already ended. The only way to join objects in a transaction in this case is to call GetPage() again.

    We have attached an example user control that creates a new page and adds some controls to it on the fly. We are definitely going to make these APIs easier and meaningful.

    Let us know if there is something else we could assist you with.

    All the best,
    Georgi
    the Telerik team

    Instantly find answers to your questions at the new Telerik Support Center
  4. Adam @Habanero
    Adam @Habanero avatar
    45 posts
    Registered:
    22 Jun 2012
    27 May 2008
    Link to this post
    Great, thanks Georgi.

    So I need to get the page again for each time I add a new control I suppose.

    It would be great if there was a way to do this with a collection of name value pairs or something.

    Cheers

    Adam
  5. Georgi
    Georgi avatar
    3583 posts
    Registered:
    28 Oct 2016
    28 May 2008
    Link to this post
    Hello Adam,

    Yes, you need to get the page each time you add new control. Our plans are to make this process easier and to make it possible to add a collection of controls at once. For this purpose, we will not commit the transaction on AddControls() method, but do it at a later stage.

    Greetings,
    Georgi
    the Telerik team

    Instantly find answers to your questions at the new Telerik Support Center
  6. Adam @Habanero
    Adam @Habanero avatar
    45 posts
    Registered:
    22 Jun 2012
    28 May 2008
    Link to this post
    Hi Georgi,

    Can you please provide an example of this because I still cannot get it working.

    I've added this call

    storePage = (ICmsPage)manager.GetPage(storePage.ID);


    After I add my first control to the page, and I then do another call to AddControl but I get the following error.

     

    Server Error in '/' Application.

    IOdbClass must be joined to a transaction.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidOperationException: IOdbClass must be joined to a transaction.

    Source Error:

    Line 147:                storePage = (ICmsPage)manager.GetPage(storePage.ID);
    Line 148:
    Line 149:                storePage.Staged.AddControl("AddressPlaceHolder", lit);
    Line 150:
    Line 151:                storePage.Staged.CheckIn();

    Source File: c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs    Line: 149

    Stack Trace:

    [InvalidOperationException: IOdbClass must be joined to a transaction.]
       Telerik.Cms.Data.StagedPage.AddControl(String containerId, String name, Control control) +357
       UserControls_TestControl.ImportStoresButton_Click(Object sender, EventArgs e) in c:\Inetpub\wwwroot\SitefinityTest\Controls\TestControl.ascx.cs:149
       System.Web.UI.WebControls.Button.OnClick(EventArgs e) +131
       System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +39
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3215
    

    Thanks
  7. Georgi
    Georgi avatar
    3583 posts
    Registered:
    28 Oct 2016
    29 May 2008
    Link to this post
    Hello Adam,

    You have to call GetPage method like this:

    page = (ICmsPage)manager.GetPage(page.IDtrue); 

    The second parameter is getting the page in Edit mode (so it joins the object to a transaction :)).
    The whole section of code should look like this:

    storePage = (ICmsPage)manager.GetPage(storePage.ID,true); 
    storePage.Staged.AddControl("AddressPlaceHolder", lit); 
    storePage = (ICmsPage)manager.GetPage(storePage.ID,true); 
    storePage.Staged.CheckIn(); 

    Note that you should call GetPage() before CheckIn() also.

    Kind regards,
    Georgi
    the Telerik team

    Instantly find answers to your questions at the new Telerik Support Center
Register for webinar
7 posts, 0 answered