0
votes

I'm having trouble getting the DateTime from a DateTimeField of an attached part I dynamically created and attached to a content type in a migration.

The structure is like this:

CourseDate (ContentType)
   ProductPart (attached part from other project)
   CourseDatePart (attached part)
   TimeSpanPart (attached part from "dynamically" created part)

I'm trying to pull the StartDateTime and EndDateTime, which are DateTimeField, out of the TimeSpanPart. However the DateTime property is always 1/1/0001

Here's the code I'm using to pull the values. Everything else works except for the TimeSpanPart.

    private EditCourseViewModel BuildEditorViewModel(CoursePart part)
    {
        var courseDates = _contentManager.Query<CourseDatePart, CourseDatePartRecord>().Where(x => x.CourseId == part.Id)
            .List<CourseDatePart>()
            .Select(x =>

                new CourseDateViewModel
                {
                    Id = x.Id,
                    StartDate = ((dynamic) x.ContentItem).TimeSpanPart.StartDateTime.DateTime,
                    EndDate = ((dynamic) x.ContentItem).TimeSpanPart.EndDateTime.DateTime,
                    Sku = ((dynamic) x.ContentItem).ProductPart.Sku,
                    IsDigital = ((dynamic) x.ContentItem).ProductPart.IsDigital,
                    Inventory = x.Inventory
                }

            );

When I inspect the value of x.Record.ContentItemRecord.Data, I can see that the data I want is there:

    <Data><TimeSpanPart><StartDateTime>2013-09-02T06:20:00.0000000</StartDateTime><EndDateTime>2013-09-21T00:05:00.0000000</EndDateTime></TimeSpanPart></Data>

Here's the relevant parts of the migration:

      ContentDefinitionManager.AlterPartDefinition("TimeSpanPart", part=>part
            .Attachable()
            .WithField("StartDateTime", f=>f.OfType("DateTimeField").WithDisplayName("Start Date Time"))
            .WithField("EndDateTime", f=>f.OfType("DateTimeField").WithDisplayName("End Date Time"))
            );

        ContentDefinitionManager.AlterTypeDefinition("CourseDate", type=>type
            .WithPart(typeof(CourseDatePart).Name)
            .WithPart("TimeSpanPart")
            .WithPart(typeof(ProductPart).Name)
            );

Edit:

I dug a bit deeper into the Orchard InfosetStorageProvider class where it manages the storage for Fields. In the BindStorage method, it's passing the Data XML element to the Get method. But instead of passing infosetPart.Infoset.Element (which has the data I want shown above), it's passing infosetPart.ContentItem.VersionRecord because it's not null; it's an empty XML element instead: <Data />

 return new SimpleFieldStorage(
                (name, valueType) => Get(infosetPart.ContentItem.VersionRecord == null ? infosetPart.Infoset.Element : infosetPart.VersionInfoset.Element, partName, fieldName, name),
                (name, valueType, value) => Set(infosetPart.ContentItem.VersionRecord == null ? infosetPart.Infoset.Element : infosetPart.VersionInfoset.Element, partName, fieldName, name, value));
        }

How do I get it to correctly populate data into infosetPart.ContentItem.VersionRecord? Is this a bug in Orchard in that it's passing an empty xml <Data /> element instead of null so that it will instead pass infosetPart.Infoset.Element to the Get method, or am I doing something wrong? I have no idea what the difference is between infosetPart.ContentItem.VersionRecord and infosetPart.Infoset.Element.

1
How does it not work?Bertrand Le Roy
For example, for the field StartDateTime.DateTime I'm expecting 2013-09-02T06:20:00, but I get 1/1/0001 instead. Can you see anything wrong with what I'm trying to do?mobese46

1 Answers

0
votes

The problem was that when creating the content item, I was setting the values of the fields before creating the content item. Because of this, it was putting the values in the table Orchard_Framework_ContentItemRecord instead of Orchard_Framework_ContentItemVersionRecord.

See here for a reported "bug" by Piedone and closed by Sebastien Ros that gave me the answer: http://orchard.codeplex.com/workitem/18412

I would have never thought of setting the values after creating the object. It still seems like something is not quite right in that if the value in the table ContentItemVersionRecord would have been set to NULL instead of <Data />, it would have worked.

Before:

            var courseDate = _contentManager.New("CourseDate");

            var courseDatePart = courseDate.As<CourseDatePart>();

            courseDatePart.CourseId = coursePart.Id;
            courseDatePart.Inventory = newDate.Inventory;

            dynamic courseDateDyn = courseDate;

            courseDateDyn.TimeSpanPart.StartDateTime.DateTime = newDate.StartDate.Value;
            courseDateDyn.TimeSpanPart.EndDateTime.DateTime = newDate.EndDate.Value;

            var product = courseDate.As<ProductPart>();

            product.Sku = newDate.Sku;
            product.IsDigital = newDate.IsDigital;

            //This should move up before setting field values.
            _contentManager.Create(courseDate);

After:

            var courseDate = _contentManager.New("CourseDate");

            var courseDatePart = courseDate.As<CourseDatePart>();

            courseDatePart.CourseId = coursePart.Id;
            courseDatePart.Inventory = newDate.Inventory;

            //This needs to happen before we set any values on the fields.
            _contentManager.Create(courseDate);

            dynamic courseDateDyn = courseDate;

            courseDateDyn.TimeSpanPart.StartDateTime.DateTime = newDate.StartDate.Value;
            courseDateDyn.TimeSpanPart.EndDateTime.DateTime = newDate.EndDate.Value;

            var product = courseDate.As<ProductPart>();

            product.Sku = newDate.Sku;
            product.IsDigital = newDate.IsDigital;