Edit Existing Content Item - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

Edit Existing Content Item

  • Edit Existing Content Item
  • I'm trying to edit an existing Event through the fluent API.  When I load the event properties in my custom form, they appear updated, but the changes are not showing up in the Sitefinity backend.  Can someone point out what I am doing incorrectly?  Here is my code used to update the event properties and resave them.

    public void PersistEvent()
        Guid id = calendarEvent.Id;
        App.Prepare().SetContentProvider(contentProviderName)
           .WorkWith().Events()
           .Where(ev => ev.Id == id)
           .ForEach(ev =>
           
               ev.Title = eventDetailCtl.txtEventName.Text;
               ev.Description = eventDetailCtl.txtDescription.Text;
               ev.EventStart = eventDetailCtl.dtEventBegin.SelectedDate.HasValue ?
                                               eventDetailCtl.dtEventBegin.SelectedDate.Value :
                                               ev.EventStart;
               ev.EventEnd = eventDetailCtl.dtEventEnd.SelectedDate.HasValue ?
                                               eventDetailCtl.dtEventEnd.SelectedDate.Value :
                                               ev.EventEnd;
               ev.Street = eventDetailCtl.txtStreet.Text;
               ev.City = eventDetailCtl.txtCity.Text;
               ev.State = eventDetailCtl.txtState.Text;
               ev.ContactEmail = eventDetailCtl.txtEmail.Text;
               ev.ContactWeb = eventDetailCtl.txtWebsite.Text;
               ev.ContactName = eventDetailCtl.txtContactName.Text;
               ev.ContactPhone = eventDetailCtl.txtContactPhone.Text;
           )
           .SaveChanges();


    Thanks.
  • Does anyone from Telerik have any input on this issue?  Is the issue caused by something I am doing incorrectly or a bug in the API?

    Thanks.
  • Hi Geoff,

    Can you check whether the data is persisted inside [sf_events] table?

    Greetings,
    Ivan Dimitrov
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • The fields are not updated in the [sf_events] table.
    The updates do not appear in the Sitefinity backend, but they do appear on my frontend page.  This applies to standard and custom fields.  I assume the changes are being persisted in a different table, since they are applied to wherever my content is loaded from on the frontend page.

    Thanks.
  • I had to do a database restore for another issue and decided to look at this issue again afterwards.  The new values are now showing up in the sf_events table, for whatever reason.  I'm not sure what I have changed that would have affected it.  I'm not sure what information you want to see from the table, but I noticed approval_workflow_state is Published and content_state is NULL.  A row with the previous value has content_state as Published.

    What causes content_state to be set?  Ideally the updated event would be resubmitted to my workflow for another approval.
    Here is my current code:

    public void PersistEvent()
        Guid id = calendarEvent.Id;
        App.Prepare().SetContentProvider(contentProviderName)
           .WorkWith().Events()
           .Where(ev => ev.Id == id)
           .ForEach(ev =>
           
               ev.Title = eventDetailCtl.txtEventName.Text;
               ev.Description = eventDetailCtl.txtDescription.Content;
               ev.EventStart = eventDetailCtl.dtEventBegin.SelectedDate.HasValue ?
                                               eventDetailCtl.dtEventBegin.SelectedDate.Value :
                                               ev.EventStart;
               ev.EventEnd = eventDetailCtl.dtEventEnd.SelectedDate.HasValue ?
                                               eventDetailCtl.dtEventEnd.SelectedDate.Value :
                                               ev.EventEnd;
               ev.Street = eventDetailCtl.txtStreet.Text;
               ev.City = eventDetailCtl.txtCity.Text;
               ev.State = eventDetailCtl.txtState.Text;
               ev.Country = eventDetailCtl.txtCountry.Text;
               ev.ContactEmail = eventDetailCtl.txtEmail.Text;
               ev.ContactWeb = eventDetailCtl.txtWebsite.Text;
               ev.ContactName = eventDetailCtl.txtContactName.Text;
               ev.ContactPhone = eventDetailCtl.txtContactPhone.Text;
           )
           .SaveChanges();
     
        if (id != Guid.Empty)
            SubmitEventToWorkflow(id);
     
    private void SubmitEventToWorkflow(Guid eventID)
        Event eventItem = App.WorkWith().Events().Where(ev => ev.Id == eventID).Get().FirstOrDefault();
        var masterId = eventItem.OriginalContentId;
     
        EventsManager.GetManager().RecompileItemUrls<Event>(eventItem);
        if (eventItem.Status == ContentLifecycleStatus.Master)
        
            EventsManager.GetManager().CheckOut(eventItem);
            masterId = eventItem.Id;
        
     
        EventsManager.GetManager().SaveChanges();
     
        var contextBag = new Dictionary<string, string>();
        contextBag.Add("ContentType", eventItem.GetType().FullName);
     
        WorkflowManager.MessageWorkflow(
                     masterId,
                     eventItem.GetType(),
                     EventsManager.GetDefaultProviderName(),
                     "SendForApproval",
                     false,
                     contextBag);

    Thanks.
  • Ivan,
    What is the relevance of the data showing up in the sf_events table?  Project completion is waiting on this issue and an issue open in another thread to get resolved, so a prompt resolution would be appreciated.  What are the next steps to get this issue resolved?

    Thanks.
  • Does anyone on the Telerik team have any input on this issue?

    Thanks.
  • Hi Geoff,

    We are very sorry for this delayed answer.

    There are three lifecycle states for each content item: Master, Live and Temp and for every content item there may be three rows with data. You can read more about these states here. The problem in your first code is that you edit directly the Live item instead of modifying the Master item and then publishing it. That's why you can see the changes in the frontend but the backend is not affected. The Sitefinity workflow besides the changing of the workflow status also manages the lifecycle status and that's why your second code works.
    I suppose you are using the Sitefinity documentation to assemble your code. But you would better use the sample for single item instead of the one for multiple items:

    public void EditEvent(Guid itemID, string newContent)
        App.WorkWith()
           .Event(itemID)
           .CheckOut()
               .Do(e =>
               
                   e.Content = newContent;
                   e.LastModified = DateTime.UtcNow;
               )
                .CheckIn()
            .SaveChanges();

    You should call Publish() to apply your changes to the frontend:

    .CheckIn()
    .Publish()
    .SaveChanges();


    Greetings,
    Ivan Pelovski
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • Thank you for responding to my issue, Ivan.  Explaining the lifecycle states helped a lot.  I am now editing the Master and am able to update the content item and have the changes show up in the Sitefinity backend.  However, I cannot get the event to be resubmitted to my workflow.

    Here is my code for resubmitting the event to the workflow, which is used successfully on event creation:
    private void SubmitEventToWorkflow(Event eventItem)
        var masterId = eventItem.OriginalContentId;
     
        EventsManager eventsManager = EventsManager.GetManager();
        eventsManager.RecompileItemUrls<Event>(eventItem);
        if (eventItem.Status == ContentLifecycleStatus.Master)
        
            eventsManager.CheckOut(eventItem);
            masterId = eventItem.Id;
        
     
        eventsManager.SaveChanges();
     
        var contextBag = new Dictionary<string, string>();
        contextBag.Add("ContentType", eventItem.GetType().FullName);
     
        WorkflowManager.MessageWorkflow(
                     masterId,
                     eventItem.GetType(),
                     EventsManager.GetDefaultProviderName(),
                     "SendForApproval",
                     false,
                     contextBag);

    On:
    eventsManager.SaveChanges();
    I get the following error:

    Object references between two different object scopes are not allowed. The object 'Telerik.Sitefinity.Workflow.Model.Tracking.ApprovalTrackingRecord' is already managed by 'ObjectScopeImpl 0x254d6cc Telerik.OpenAccess.RT.ObjectScope' and was tried to be managed again by 'ObjectScopeImpl 0xae7186 Telerik.OpenAccess.RT.ObjectScope'.


    I'm not sure what this error message is referring to as I'm unfamiliar with ApprovalTrackingRecords and how they are managed in the system.  Could you give me some direction on how to get this resolved, Ivan?

    Thanks.
  • Hello Geoff,

    Thank you for coming back to us.
    This error often appears if you get a data item within one transaction and try to edit and save it in another transaction. In these cases you should retrieve the data item again so that the changes to be part of one transaction.
    private void SubmitEventToWorkflow(Event eventItem)
        EventsManager eventsManager = EventsManager.GetManager();
        var eventItem2 = eventsManager.GetEvent(eventItem.Id);
        // continue work with eventItem2
        // ...


    All the best,
    Ivan Pelovski
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • Ivan, thanks for your help so far.  I updated my SubmitToWorkflow method with your code and I am no longer getting the error, however I am now having another issue.  The event is being saved correctly, but is not properly entering the workflow.

    With the following piece of code:
    if (eventItem.Status == ContentLifecycleStatus.Master)
        eventsManager.CheckOut(eventItem);
        masterId = eventItem.Id;

    If I comment out the .CheckOut line, then the event is saved, but not published and it does not enter the workflow.
    If I leave the .CheckOut line uncommented, the event is saved, but is locked by the user.

    Should I be submitting the Master version of the event to the workflow, or should I be using the Live or Temp versions?
    Since the event changes save correctly without calling .CheckOut on the event, should I be calling it?  What is the benefit?  If I should be calling .CheckOut, how do I check the event in so that it is not locked by the user?  When I call eventsManager.CheckIn(eventItem), I get the error "Cannot check in item that is not in temp state".

    Thanks.
  • Hi Geoff,

    Thank you for coming back to us.
    I am not sure what you are trying to do. You are calling the workflow with "SendForApproval" operation but you want it to be published. You would better call it with "Publish" workflow operation. When you call the workflow you should pass the id of the master version.

    If you want to change an item then you check it out, perform the changes to the temp version and then call CheckIn for the temp version. Checking the temp version in will copy the data of the temp to the master version. You may make changes to the master version directly but the more proper way is to go from master to temp and then back to master version.

    Greetings,
    Ivan Pelovski
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
  • Sorry for the confusion.  My process is this:
    A frontend user can view and edit an existing event.  Upon editing the event, the user submits the event for publishing.  This event enters the workflow and must be approved before being published.  A user of an approved role can view the event through the Sitefinity backend and then publish the event through the backend.

    So I'm only looking for workflow submission from the frontend.  The publishing can take place through the workflow on the Sitefinity backend.  My original problem was that events were not entering the workflow (as they are still not) and the changes to metadata were not showing up on the backend (because I was modifying the wrong version of the event).  The changes appearing on the frontend were an unwanted side effect of me editing the wrong version of the event.

    Currently the changes are appearing in the backend, and I would like these changes to be published until they have been approved in the workflow.

    I hope this makes more sense.

    So my question is, how is submitting a newly created event to a workflow different from submitting an existing, edited event to a workflow?  I cannot get my workflow submission code, which works on newly created events, to work correctly on already existing events.

    Thanks.
  • 273147_WorkflowSwitchLinks.png
    Hi Geoff,

    Some of the item's states will not allow to you to edit them and you have to check this before you allow the user to modify them. If you enter in edit mode of the item , the item should be in draft state according our workflow logic.  When a user save the item it should be in awaiting approval state. You can use WorkflowMenu control or the other way is to implement your custom code for this. Manually you could invoke the workflow with this code :

    The workflowOperation value should be equal to the value of the FlowSwitchLink (see the attached file)

    if (content.SupportsContentLifecycle && !string.IsNullOrEmpty(workflowOperation))
                       
                           var item = this.Manager.CheckOut(content);
                           this.Manager.SaveChanges();
     
                           var contextBag = new Dictionary<string, string>();
                           contextBag.Add("ContentType", item.GetType().FullName);
                           contextBag.Add("MasterId", content.Id.ToString());
     
                           WorkflowManager.MessageWorkflow(
                               item.Id,
                               content.GetType(),
                               providerName,
                               workflowOperation,
                               false,
                               contextBag
                             );
                       


    All the best,
    Teodor
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>