Update Contents via Code not working correct

Topics: Core, Customizing Orchard, Troubleshooting
Sep 10, 2013 at 10:59 AM
Edited Sep 10, 2013 at 11:01 AM
I am trying to update the creationdate of a list of contents via the contentmanager, the problem is that the contentmanager tells me all files are updated but in fact in reality nothing happened.
I use the creation date to order my content list in the projection, what I want to achieve is that if a contents creationdate is older than 2 weeks, set the date to now and publish, in order to get them back on top in the list.

I also use the Creation Date as a Field within my Content, to enable the Users to modify it manually.

This is my code:
        IEnumerable<ContentItem> jobs = _contentManager.Query("Job_DE").List();
        var contentItems = jobs as ContentItem[] ?? jobs.ToArray();
        int counter = 0;
        try
        {
            //Manipulate the dates
            if (jobs != null && contentItems.Any())
            {
                foreach (ContentItem job in contentItems)
                {
                    foreach (ContentPart jobPart in job.Parts)
                    {
                        var contentString = jobPart.ToString();

                        //handle the publish date
                        if (contentString.Contains("CommonPartVersionRecord"))
                        {
                            ContentPart<CommonPartVersionRecord> com = jobPart as ContentPart<CommonPartVersionRecord>;
                            if (com != null && Convert.ToDateTime(com.Record.CreatedUtc).AddDays(+14) < DateTime.Now)
                            {
                                com.Record.CreatedUtc = DateTime.Now;
                                com.Record.ModifiedUtc = DateTime.Now;
                                _contentManager.Publish(job);
                                counter++;
                            }
                        }
                    }
                }
            }
            _contentManager.Flush();
        }
        catch (Exception ex)
        {
            return "There was an Error: " + ex.Message;
        }
        return "Updated " + counter + " Job items.";
Any ideas ??
cheers
Sep 10, 2013 at 11:45 AM
CreationDate might be readonly. You might add a new datetime field to your part, try updating that field with the same logic, and order by it.


Sep 10, 2013 at 12:30 PM
Hi,
thanks for the answer, actually it seems not to be readonly because when i rerun my method it says all contents have the new creation date of DateTime.Now but when I view my Contents within the Web.UI --> only the Published Date has changed. From my point of view there is a problem between the content field creation date and the real creation date within the DB.
greetz
Coordinator
Sep 10, 2013 at 7:40 PM
It is not read-only: there is an editor for it. Look at the code for the common part driver.
Sep 10, 2013 at 8:20 PM
Hi Bertrand,
could you explain that a little more precisely, or maybe drop a code snippet ? Why do I need an editor anyways for updating a DB field via code ?
Thanks for your help.
cheers
Coordinator
Sep 10, 2013 at 8:28 PM
Not following you. Do you want me to copy the code from the driver here?
Sep 10, 2013 at 9:13 PM
?? what driver do you mean - sorry but i don't get it. I pasted my code - just tell me what I am doing wrong in there or what#s missing to set the creationUtc date for my contents. Again my friend - sorry Bertrand I know ya hearing a lot a stupid questions a day but I am sick of figuring out workarrounds to get control of the orchard datasets.
pce and greetz
Coordinator
Sep 10, 2013 at 9:17 PM
The common part driver. What I'm saying is that this driver is already doing what you are trying to do, so you should be able to see how it's done by looking at its code.
Sep 10, 2013 at 9:21 PM
You mean this ?
        var model = new ContainerEditorViewModel();
        if (part.Container != null)
            model.ContainerId = part.Container.ContentItem.Id;

        if (updater != null) {
            var priorContainerId = model.ContainerId;
            updater.TryUpdateModel(model, Prefix, null, null);

            if (model.ContainerId != null && model.ContainerId != priorContainerId) {
                var newContainer = _contentManager.Get((int)model.ContainerId, VersionOptions.Latest);
                if (newContainer == null) {
                    updater.AddModelError("CommonPart.ContainerId", T("Invalid container"));
                } else {
                    part.Container = newContainer;
                }
            }
        }
Sep 10, 2013 at 9:23 PM
or the part done when importing ?
        var createdUtc = context.Attribute(part.PartDefinition.Name, "CreatedUtc");
        if (createdUtc != null) {
            part.CreatedUtc = XmlConvert.ToDateTime(createdUtc, XmlDateTimeSerializationMode.Utc);
        }
Coordinator
Sep 10, 2013 at 9:29 PM
The first one.

Did you put breakpoints in your code to verify that it is getting hit?
Coordinator
Sep 10, 2013 at 9:31 PM
Oh wait. I thought it was the creation date you wanted to modify, not the last modified date. Yes, well, last modification date is always going to be overwritten by Orchard, you can't set it yourself reliably.
Sep 10, 2013 at 9:36 PM
well the modifiedLastUtc is not the problem, i sort my projection by the creationUtc, if i can set that the thing is running, so I'll just update my code according to the commonpartdriver and then I'll get back to you ;). thx 'til now. I'll report my result.
cheers
Sep 10, 2013 at 9:37 PM
and yeah Bertrand - I debugged the hell out a that method :). thx for now
Coordinator
Sep 10, 2013 at 10:07 PM
The call to Flush looks suspicious, too, but more as a symptom of other problems. I don't think you should have to do that.
Sep 19, 2013 at 8:47 AM
Still not working, I now use the updater.TryUpdateModel, the problem is that the IUpdateModel is never injected and always null. Do I have to initiated differently or is there something missing:
    private readonly IContentManager _contentManager;
    private readonly ITaxonomyService _taxonomyService;
    private readonly IUpdateModel _updateModel ;

    protected string Prefix
    {
        get { return "CommonPart"; }
    }

    public XMLCreatorService(IContentManager contentManager, ITaxonomyService taxonomyService, IUpdateModel updateModel)
    {
        _contentManager = contentManager;
        _taxonomyService = taxonomyService;
        _updateModel = updateModel;
    }
.
.
.
                            ContentPart<CommonPartVersionRecord> com = jobPart as ContentPart<CommonPartVersionRecord>;
                            if (com != null && Convert.ToDateTime(com.Record.CreatedUtc).AddDays(+14) > DateTime.Now) {
                                com.Record.CreatedUtc = DateTime.Now;
                                if (_updateModel != null) {
                                    _updateModel.TryUpdateModel(jobPart, Prefix, null, null);
                                }
                                _contentManager.Publish(job);
                                counter++;
                            }
Sep 19, 2013 at 12:13 PM
Edited Sep 19, 2013 at 12:13 PM
Anyways it seems the DB is updated correctly, even when I just use Publish but the field used within the content is not updated.
See below pic:
Image
cheers!
Coordinator
Sep 19, 2013 at 10:11 PM
IUpdateModel is not an IDependency, you don't inject it, it gets passed into methods that need it. Not sure why your fields don't get updated.
Sep 20, 2013 at 12:26 PM
Hi Bertrand, thanks for the info. I found out that there's actually no need to use the TryUpdateModel. The problem was that I always updated the wrong ContentPart as you can see in my first posted code, I modified the Record of the CommonPartVersionRecord. The key is to update the CommonPartRecord of the ContentItem, then everything is updated correctly ;).

This is the working code:
            //Manipulate the dates
            if (jobs != null && contentItems.Any())
            {
                foreach (ContentItem job in contentItems)
                {
                    ContentItem latestJob = _contentManager.Get(job.Id, VersionOptions.Latest);
                    foreach (ContentPart<CommonPartRecord> com in from jobPart in latestJob.Parts let contentString = jobPart.ToString() where contentString.Contains("CommonPart") select jobPart as ContentPart<CommonPartRecord> into com where com != null && Convert.ToDateTime(com.Record.CreatedUtc).AddDays(+14) < DateTime.Now select com)
                    {
                        DateTime _now = DateTime.Now;
                        com.Record.CreatedUtc = _now;
                        com.Record.ModifiedUtc = _now;
                        _contentManager.Publish(latestJob);
                        counter++;
                    }
                }
                _contentManager.Flush();
            }
Cheers!
Marked as answer by AlCoPaine on 10/8/2013 at 3:44 AM