U4-10713 - ContentService API bug getting latest content version via GetById method

Created by Andreas Kaltenhuber 23 Nov 2017, 11:41:24 Updated by Jose Marcenaro 04 Aug 2018, 11:25:12

What did you do?

we have a multi-step form where members can edit content. we have around 20 properties so for a good "ux" we have grouped the properties into several "steps":

Step 0 - Create content node Member creates content via surfacecontroller

  • Contentservice.CreateContent
  • ContentService.SaveAndPublishWithStatus

Step 1-4 Edit content node Members edits content via surfacecontroller

  • Contentservice.GetById
  • ContentService.SaveAndPublishWithStatus

What did you expect to happen?

That whenever a member edits information via surfacecontroller, all information is persisted and doesn't get lost. this behavior worked before without and issues.

What actually happened?

Since our upgrade from 7.5.13 => 7.7.6 content gets lost. the code worked for around half a year without any problems. so there must have been a change regarding persistence etc.

we still have an installation with 7.5.13 running 100% the same code, and there we don't have any troubles. the troubles on 7.7.6 started with the upgrade. both projects are on UAAS.

here is maybe some useful information about what is wrong regarding published content versions and loading the latest version of a node via contentservice

STEP0 CreateContent SaveAndPublishWithStatus => PublishedVersionGuid = {718a60df-68cf-45fc-9101-d8bcec53fac3}

STEP1 GetById => Loaded Version = {718a60df-68cf-45fc-9101-d8bcec53fac3} SaveAndPublishWithStatus => PublishedVersion = {0c5b3f94-de06-4d7f-a47f-8f287bf594ea}

STEP2 GetById => Loaded Version = {718a60df-68cf-45fc-9101-d8bcec53fac3} SaveAndPublishWithStatus => PublishedVersion = {245764bb-1b8b-4ca5-9b19-08c788222a56}

STEP3 GetById => Loaded Version = {718a60df-68cf-45fc-9101-d8bcec53fac3} SaveAndPublishWithStatus => PublishedVersion = {245764bb-1b8b-4ca5-9b19-08c788222a56}

... ...

on step 2 and so on you can see the ISSUE: the wrong content version gets loaded. so whenever we call contentservice.getbyid(key) we get the first/inital version of the node and not the latest!!

please have an look on that issue as it was working before and is an show stopper when working with contentservice api.

thx for your help, Andreas

Comments

Warren Buckley 24 Nov 2017, 11:30:16

Hi @Andreas.Kaltenhuber I have looked at this and done a quick & dirty example of getting the content item and saving it multiple times and can verify that the version gets updated correctly.

Here is my quick & dirty example I tried this with:

    public class HomeController : RenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            //Get content
            var contentNode = Services.ContentService.GetById(1126);

            //Update something
            contentNode.Name += "UPDATED";

            //Save & publish
            var savedStatus = Services.ContentService.SaveAndPublishWithStatus(contentNode);

            //Get content again
            var contentNodeUpdated = Services.ContentService.GetById(1126);

            //Update again
            contentNodeUpdated.Name += " - AND AGAIN";

            //Save & publish
            var savedStatusAgain = Services.ContentService.SaveAndPublishWithStatus(contentNodeUpdated);

            //Get Content again & verify its persisted
            var finalCheck = Services.ContentService.GetById(1126);


            //Do some stuff here, then return the base method
            return base.Index(model);
        }
    }

If you can give me some more information or details to reproduce this that would be great.

Thanks, Warren


Andreas Kaltenhuber 24 Nov 2017, 12:31:28

Hi @warren.buckley,

alright. after you call SaveAndPublish "print out" the version id of the published content. then when you load the node again (getbyid should load the version you just saved) you will see when you print out the version id of the content you just loaded that this is not the last version, it is the first version of the content. so you will actually see this when you print put finalCheck.Version that the version is not equal to the savedStatusAgain convent version guid.

hope i could explain that.

when you run the script on 7.5.13 the content versions are correct and getbyid return always the latest version that was saved for that node. on 7.7.6 i always get the first content version of that node.

at the moment i found that workaround for 7.7.6 to get the latest content for a node:

var service = ApplicationContext.Current.Services.ContentService; var latestContentVersion = service.GetVersionIds(1234, 1).First(); var node = service.GetByVersion(latestContentVersion);

actually getbyid should do this by design.

thx for your help, andreas


Andreas Lorenz 24 Nov 2017, 13:37:02

Hi @warren.buckley ,

to make it easier for you to understand what @Andreas.Kaltenhuber means, here is a test code from our side. This is how we debugged the issue and came up with the ticket. Hope it helps your to easier understand the issue.

var service = ApplicationContext.Current.Services.ContentService;

        // step 0 - create
        var node = service.CreateContent("123Project", 1169, "dataProject");
        node.Name = "TestCreate";

        var publish = service.SaveAndPublishWithStatus(node);
        if (publish.Success)
        {
            Response.Write("<br>STEP0 (Create): Published Version: " + publish.Result.Entity.PublishedVersionGuid + " // NodeName: " + node.Name);
        }

        var nodeKey = node.Key;

        // step 1 - edit1
        var edit1 = service.GetById(nodeKey);
        Response.Write("<br>STEP1 (Edit-1): Loaded Version: " + edit1.Version + " // NodeName: " + edit1.Name);
        edit1.Name = "Edit1";


        publish = service.SaveAndPublishWithStatus(edit1);
        if (publish.Success)
        {
            Response.Write("<br>STEP1 (Edit-1): Published Version: " + publish.Result.Entity.PublishedVersionGuid + " // NodeName: " + edit1.Name);
        }

        // step 2 - edit2
        var versions = service.GetVersionIds(node.Id, 100);
        var latest = versions.First();
        foreach(var v in versions)
        {
            Response.Write("<br>Version: " + v);
        }

        var edit2 = service.GetByVersion(latest);
        Response.Write("<br>STEP2 (Edit-2): Loaded Version: " + edit2.Version + " // NodeName: " + edit2.Name);
        edit2.Name = "Edit2";

        publish = service.SaveAndPublishWithStatus(edit2);
        if (publish.Success)
        {
            Response.Write("<br>STEP2 (Edit-2): Published Version: " + publish.Result.Entity.PublishedVersionGuid + " // NodeName: " + edit2.Name);
        }

        // step 3 - edit3
        var edit3 = service.GetById(nodeKey);
        Response.Write("<br>STEP3 (Edit-3): Loaded Version: " + edit3.Version + " // NodeName: " + edit3.Name);
        edit3.Name = "Edit3";

        publish = service.SaveAndPublishWithStatus(edit3);
        if (publish.Success)
        {
            Response.Write("<br>STEP3 (Edit-3): Published Version: " + publish.Result.Entity.PublishedVersionGuid + " // NodeName: " + edit3.Name);
        }

        var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
        var publishedContent = umbracoHelper.TypedContent(nodeKey);

        Response.Write("<br>This is the document in the cache - nodename should be <strong>" + node.Name + "</strong> but is: " + publishedContent.Name);
        Response.Write("<br>PublishedVersion should be <strong>" + publish.Result.Entity.PublishedVersionGuid + "</strong> but is: " + publishedContent.Version);

}

Currently we came up with following workaround:

// we first get the latest content version and instead of .GetById(id) we use .GetByVersion

var service = ApplicationContext.Current.Services.ContentService; var latestContentVersion = service.GetVersionIds(Convert.ToInt32(form.Get("ProjectId")), 2).First(); var node = service.GetByVersion(latestContentVersion);

Thanks in advance. Andreas


Andreas Kaltenhuber 29 Nov 2017, 09:32:10

Hi @warren.buckley,

we investigated further on the issue and i think we have found the problem now. it depends if you load the Node via its ID or via its KEY.

when you use ContentService.GetById(int) umbraco works as expected and loads the latest published content of the node.

on the other hand when you use ContentService.GetById(guid) umbraco loads the first published content version of the node.

i have a working umbraco installation to reproduce that (fresh install with startkit on 7.7.6, compared to a fresh install without that bug on 7.5.13) i can send you a zip if wanted.

thanks for your help, Andreas


Jose Marcenaro 04 Aug 2018, 11:25:12

Hi @Andreas.Kaltenhuber @warren.buckley

I stumbled with the exact bug still happening on v7.10.4 --> thanks Andreas for your report! It clarified why my code wasn't working.

I just upgraded to v7.11.1 and it is fixed - I don't know on which version it was fixed.

Thanks, Jose


Priority: Normal

Type: Bug

State: Submitted

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.7.6

Due in version:

Sprint:

Story Points:

Cycle: