SaaS CMS has officially launched! Learn more now.

Content provider - problems with edit UI

Vote:
 

Hi,

I have been creating a content provider for external videos (well tried at least). The provider it self seems to work just fine, and going in to "admin mode -> Set access rights" I can find my root folder pluss all the videos.

The problem for me occurs when I include the [Component] for viewing these items in the edit UI. The UI after a build loads up so I can see the content tree and assets (not the videos though), but the pages does not load in the "edit area", and a refresh of the page leaves everything blank, exept the top menu to navigate to admin mode and so on.  I have had this error before, and never finished my content provider, but now I had the time to take another look at it.I get no Javascript error or anything in the epilog either.

So, just to see if I could get a simple one to work I created a completly fresh install of Epi, upgraded it to latest as of today. And added the simplest example I could. Still get the same error. Therefore I am turning to you, the elite, to see if I have left something out as I am starting to get blinded by my code. I have been using the HierarcicalList for showing my elements ( I have tried several of the other ones as well). What I did find out is that if I create my own little dojo, just outputting "This is some static text" everything works just fine (appart from not showing the elements of course). I'll include the code here in hopes of anyone seeing my fault/problem.

public class PersonContentProvider : ContentProvider
    {
        public static string Key = "Persons";

        public override ContentProviderCapabilities ProviderCapabilities
        {
            get { return ContentProviderCapabilities.Create | ContentProviderCapabilities.Edit; }
        }
        private List _items = new List();
        
        protected override IContent LoadContent(ContentReference contentLink, ILanguageSelector languageSelector)
        {
            var item = _items.FirstOrDefault(p => p.ContentLink.Equals(contentLink));
            if (item == null)
            {
                item = _items.FirstOrDefault(p => p.ContentLink.CompareToIgnoreWorkID(contentLink));
            }

            return item;
        }
        protected override IList LoadChildrenReferencesAndTypes(ContentReference contentLink, string languageID, out bool languageSpecific)
        {
            languageSpecific = false;

            return _items
               .Where(p => p.ParentLink.ID.Equals(contentLink.ID))
               .Select(p => new GetChildrenReferenceResult { ContentLink = p.ContentLink, ModelType = typeof(EpiPerson) }).ToList();
        }
        public void RefreshItems(List items)
        {
            _items = items;
            ClearProviderPagesFromCache();
        }
    }
[InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class PersonInitialization : IInitializableModule
    {
        protected Injected ContentFactory { get; set; }
        protected Injected ContentTypeRepository { get; set; }
        protected Injected IdentityMappingService { get; set; }
        public void Initialize(InitializationEngine context)
        {
           // Register person IContentData type
            var registerPerson = context.Locate.Advanced.GetInstance>();
            registerPerson.RegisterType();

            var contentRepository = context.Locate.ContentRepository();
            var entryPoint = contentRepository.GetBySegment(ContentReference.RootPage, PersonContentProvider.Key, LanguageSelector.AutoDetect(true)) as BasicContent;
            
            if (entryPoint == null)
            {
                entryPoint = contentRepository.GetDefault(ContentReference.RootPage);
                entryPoint.Name = PersonContentProvider.Key;
                contentRepository.Save(entryPoint, SaveAction.Publish, AccessLevel.NoAccess);
            }

            // Register custom content provider
            var providerValues = new NameValueCollection
            {
                {ContentProviderElement.EntryPointString, entryPoint.ContentLink.ID.ToString()},
                {ContentProviderElement.CapabilitiesString, ContentProviderElement.FullSupportString}
            };

            var personProvider = new PersonContentProvider();
            personProvider.Initialize(PersonContentProvider.Key, providerValues);
            
            var providerManager = context.Locate.Advanced.GetInstance();
            providerManager.ProviderMap.AddProvider(personProvider);

            // Refresh content
            try
            {
                Task.Run(() => Refresh(personProvider, entryPoint, contentRepository));
            }
            catch (Exception ex)
            {
                //write som log
            }
        }

        private void Refresh(PersonContentProvider personProvider, BasicContent entryPoint, IContentRepository repository)
        {
            var createdPersons = new List();
            var persons = PersonHelper.GetAllPersons();
            foreach (var externalPerson in persons)
            {
                var type = ContentTypeRepository.Service.Load();
                var person = ContentFactory.Service.CreateContent(type, new BuildingContext(type)
                {
                    Parent = entryPoint,
                    LanguageSelector = LanguageSelector.AutoDetect(),
                    SetPropertyValues = true
                }) as EpiPerson;

                if (person != null)
                {
                    createdPersons.Add(PopulatePerson(person, externalPerson));
                }
            }

            personProvider.RefreshItems(createdPersons);
        }

        public EpiPerson PopulatePerson(EpiPerson person, ExternalPerson externalPerson)
        {
            if (externalPerson != null)
            {
                Uri externalId = MappedIdentity.ConstructExternalIdentifier(PersonContentProvider.Key, externalPerson.Id.ToString());
                MappedIdentity mappedContent = IdentityMappingService.Service.Get(externalId, true);
                person.ContentLink = mappedContent.ContentLink;
                person.ContentGuid = mappedContent.ContentGuid;

                person.Name = externalPerson.Name;

                person.Created = DateTime.Now.Subtract(new TimeSpan(2, 0, 0, 0));
                person.Changed = DateTime.Now.Subtract(new TimeSpan(2, 0, 0, 0));
                person.IsPendingPublish = false;
                person.StartPublish = DateTime.Now.Subtract(new TimeSpan(1, 0, 0, 0));
                person.Status = VersionStatus.Published;
                person.MakeReadOnly();
            }
            return person;
        }
}
public class PersonHelper
    {
        public static List GetAllPersons()
        {
            return new List
            {
                new ExternalPerson {Id = 1, Name = "Batman"},
                new ExternalPerson {Id = 2, Name = "Batwoman"},
                new ExternalPerson {Id = 3, Name = "Superman"},
            };
        }
    }

    public class ExternalPerson
    {
        public int Id { get; set; } 
        public string Name { get; set; }
    }
    [ContentType(DisplayName = "EpiPerson", GUID = "ec801da9-aee5-4d7f-83ed-8138778ad70a", Description = "")]
    public class EpiPerson : ContentBase
    {

    }
[ServiceConfiguration(typeof(IContentRepositoryDescriptor))]
    public class PersonsRepositoryDescriptor : ContentRepositoryDescriptorBase
    {
        protected Injected ContentProviderManager { get; set; }
        public override string Key
        {
            get { return PersonContentProvider.Key; }
        }

        public override string Name
        {
            get { return "EPi Persons"; }
        }

        public override IEnumerable Roots { get { return new[] { ContentProviderManager.Service.GetProvider(PersonContentProvider.Key).EntryPoint }; } }
        
        public override IEnumerable ContainedTypes { get { return new[] { typeof(EpiPerson) }; } }
        
        public override IEnumerable MainNavigationTypes { get { return new[] { typeof(ContentFolder) }; } }
        
        public override IEnumerable CreatableTypes { get { return new[] { typeof(EpiPerson) }; } }

        public override int SortOrder
        {
            get { return 400; }
        }

        public bool ChangeContextOnItemSelection { get { return true; } }

        public override IEnumerable PreventContextualContentFor
        {
            get
            {
                return new[]
                {
                    ContentReference.RootPage.ToString(),
                    ContentReference.WasteBasket.ToString(),
                    ContentReference.GlobalBlockFolder.ToString()
                };
            }
        }
    }
[Component]
    public class PersonsComponent : ComponentDefinitionBase
    {
        public PersonsComponent()
            : base("epi-cms.widget.HierarchicalList")
            //: base("persons.components.Testmodel")
        {
            Categories = new string[] { "content" };
            Title = "Epi persons";
            Description = "All persons";
            SortOrder = 1000;
            PlugInAreas = new[] { PlugInArea.AssetsDefaultGroup };
            Settings.Add(new Setting("repositoryKey", PersonContentProvider.Key));

        }
    }

If I use the testmodel in the component, which is coded like below, the UI loads just fine.

define([
    "dojo/_base/declare",
    "dijit/_WidgetBase",
    "dijit/_TemplatedMixin"
],

function (
    declare,
    _WidgetBase,
    _TemplatedMixin
) {
    return declare("Testmodel",
        [_WidgetBase, _TemplatedMixin], {
            templateString: '
This is a static text shown in the assets pane
' }); });
#151145
Jul 12, 2016 12:20
Vote:
 

Hi Petter.

I think it would be helpful to turn on debugging for Episerver's DOJO implementation. Atleast I've experienced that errors aren't propagating and understanding what's causing a malfunction are therefore hard.

Try and add following to your <EPiServer.Framework/> configuration section and see if that helps you getting closer:


<clientResources debug="true"/>

Casper Aagaard Rasmussen

 

#151152
Jul 12, 2016 15:18
Vote:
 

I'm experiencing the exact same thing that Petter is describing. 

After a little bit of investigation I see that the following JS exception is thrown when trying to load the component:

TypeError: Cannot read property 'some' of null(…) "TypeError: Cannot read property 'some' of nul

A little more debugging, and I see that "this.containedTypes" inHierarchicalListViewModel.js is always null, and that's why the exception is thrown.

Unfortunately I don't know why containedTypes is null, as it's properly set in the repository descriptor. 

This has worked just fine in previous versions of EPiServer, so I suspect there's a bug or a breaking change I haven't noticed.

#151175
Jul 12, 2016 23:04
Vote:
 

After a lot of frustration and debugging I've finally found the solution to this issue.

It seems like a bug in how the RepositoryKey formatted in javascript.

I have the following repository descriptor:

[ServiceConfiguration(typeof(IContentRepositoryDescriptor))]
    public class TestItemDescriptor : ContentRepositoryDescriptorBase
    {
        public static string RepositoryKey => "TestItemRepository";
        public override string Key => RepositoryKey;

....


Notice the formatting of the RepositoryKey "TestItemRepository".

When EPiServer loads HierarchicalListViewModel.js, it reads the repository as an argument for the postscript method:

postscript: function (args) {
            this.inherited(arguments);
            this.contentRepositoryDescriptors = this.contentRepositoryDescriptors || dependency.resolve("epi.cms.contentRepositoryDescriptors");

            declare.safeMixin(this, this.contentRepositoryDescriptors[args.repositoryKey]);

args.repositoryKey is then formatted as "testItemRepository", while the property in this.contentRepositoryDescriptors is as formatted in the repository descriptor ("TestItemRepository").

This causes this.contentRepositoryDescriptors[args.repositoryKey] in the above code not to find the descriptor, and returning null values.

Changing the repository key in the repository descriptor (C#) to "testItemRepository" fixes the problem - so that's the workaround. :)

#151176
Jul 12, 2016 23:33
Vote:
 

Nice catch! Please report it as a bug to get it fixed :)

#151179
Jul 13, 2016 7:29
Vote:
 

Hi again, first of all, your help have saved me quite a bit of hair on my head!

I tried Caspers answer by turning on debugging, this was a great tip that I wasn't aware of, and will be using more if I experiece wierd UI stuff! By the time I could test these answers Øyvind had allready been working, and the fix for this surly works for me as well. Great catch as Daniel says! Thank you both for the good and quick help, this is why in my original post i said I would turn to the elite for answers ;)

I'm currently working on reporting this as a Bug to Epi, so this can be looked at.

Thanks again, Petter

#151185
Jul 13, 2016 9:38
Vote:
 

Just updating the post with registered bug i.e #CMS-4070.

Thanks for your feedback. 

#151187
Jul 13, 2016 10:10
Vote:
 

Thanks for reporting the bug. Didn't get around to doing myself yet. :) 

#151283
Jul 13, 2016 19:01
Vote:
 

Bug was fixed in CMS UI 10.6.0, released February 20, 2017.

#175485
Feb 21, 2017 20:33
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.