lazy-loadingorchardcms

Orchard Cms Fetching UserPart Field Data in LazyField<T>


I've been Following this post To get my head around Lazy field of T, Which I think I understand, But I'm having trouble getting associated Field Data for a Part loaded this way

Aim - To show photo of blog post author on a blog post.

For the first part I have created the content type and used the lazy Filed of UserPart to get the username. However when I try and get the associated fields for the UserPart. There dosent seem to be any.

public class ContentAuthorRecord : ContentPartRecord
{
    public virtual string AuthorEmail { get; set; }
}

public class ContentAuthorPart : ContentPart<ContentAuthorRecord>
{
    internal readonly LazyField<UserPart> Owner = new LazyField<UserPart>();

    public string AuthorEmail
    {
        get { return Record.AuthorEmail; }
        set { Record.AuthorEmail = value; }
    }

    public UserPart Author
    {
        get { return Owner.Value; }
        set { Owner.Value = value; }
    }

    public string AuthorName
    {
        get
        {
            if (Author == null)
                return "Riders for health";
            else
            {
                return Author.UserName;
            }
        }

    }
}



public class ContentAuthorHandler :ContentHandler
{
        private readonly IContentManager _contentManager;

        public ContentAuthorHandler(IRepository<ContentAuthorRecord> repository, IContentManager contentManager)
        {
            _contentManager = contentManager;

            OnActivated<ContentAuthorPart>(SetUpCustomPart);
            Filters.Add(StorageFilter.For(repository));
        }

        private void SetUpCustomPart(ActivatedContentContext content, ContentAuthorPart part)
        {

            // Setup the getter of the lazy field
            part.Owner.Loader(() => _contentManager.Query<UserPart, UserPartRecord>().List().FirstOrDefault(x => x.Email == part.AuthorEmail));

        }

  }

I would expect to be able to access the field with something like

(ImageUploadField.Fields.ImageUploadField)Author.Fields.FirstOrDefault(x => x.Name == "Photo");

form the within the part class

( although this makes every thing a bit brittle, hard coding a field name, but I'm not sure how eles to go about it)

Further Info

I have a HeaderPart with a Image field added via the cms (not in code) in the display handler I fetch the field like this

 protected override DriverResult Display(HeaderPart part, string displayType, dynamic shapeHelper)
        {
            if (part.HeaderType == HeaderType.Full_width_hero_image)
            {
                var field = (ImageUploadField) part.Fields.FirstOrDefault(f => f.Name == "HeaderImage");

                if (field != null)
                {
                    return ContentShape("Parts_Header_ImageHero",
                        () => shapeHelper.Parts_Header_ImageHero(ImagePath: field.ImagePath, ImageTitle: field.FileName));
                }
                return null;
            }
            if (part.HeaderType == HeaderType.Full_width_hero_video)
            {
                return ContentShape("Parts_Header_VideoHero", () => shapeHelper.Parts_Header_VideoHero(VideoUrl: part.VideoUrl));
            }
            if (part.HeaderType == HeaderType.Body_width_video)
            {
                return ContentShape("Parts_Header_VideoBody", () => shapeHelper.Parts_Header_VideoBody(VideoUrl: part.VideoUrl));
            }
            return null;
        }

This works, But I can do the same for a part loaded into a lazy field.


Solution

  • If you have added the fields to the User content type via the CMS interface, it may have added the fields to a different part to the one you expect. If you are adding fields to the User content type, by default it will have added the fields to a new part called 'User', not 'UserPart'. Try to following to search all parts in the content item:

    (ImageUploadField.Fields.ImageUploadField)Author.ContentItem.Parts
    .SelectMany(p => p.Fields).FirstOrDefault(f => f.Name == "Photo");
    

    or directly from the 'User' part:

    (ImageUploadField.Fields.ImageUploadField)Author.ContentItem.Parts
    .First(p => p.PartDefinition.Name == p.ContentItem.ContentType).Fields
    .FirstOrDefault(f => f.Name == "Photo");