This project is read-only.

Loading parts..

Topics: Troubleshooting, Writing modules
Mar 16, 2011 at 4:46 PM

I ran into this before and now again, before i just ignored and did a request from the cache which isn't that need when we'll have 500+ parts.

This time it's even differend.
I've a part that needs to be loaded with data from a webservice, but that webservice should only be accessed when the part will be visible.
I made a new layer and a own custom widget, added the widget to the layer and that layer has a rule that it's visible on a specific route.

But even thru the ruleengine says that the widget isn't visible since the route rule is invalid, the contentitem and the parts are still loaded.
I figured it out and the only place i get this working is in a parthandler overriding OnDisplaying and filtering on the ContentItemType
Another workaround is doing this in the driver "factory method" passed into the ContentResult.

However this feels wrong.
All parts are being loaded? Always?
At least the parts belonging to a widget are always loaded, even thru they won't ever be visible.
Each StorageFilter for a part within the widget does query the database..

Are there any plans to improve this, i don't think this is by design? 

For example LazyLoading parts only if they are being touched.

Mar 17, 2011 at 9:54 PM

At the moment all of widgets are selected in a single query, rather than select them with multiple queries, on the assumption that would reduce the database impact. It is true that has the effect of initializing those as content items with all of the parts being welded and firing the loading/ed events.

But one thing to keep in mind is that the ContentPart<TRecord> Record property is actually lazy-loaded when it is first accessed - not when the loading/ed events fire. The loading event really just wires the lazy field callback so the driver can acquire the data when needed.

You could consider doing the same thing for your part that's exposing data from a web service... Let's say you have LazyField<FooData> Foo; on the part where FooData is a class from the web service data contract. Your driver's loading event could call part.Foo.Loader(()=>{ lazy called code to return FooData somehow - possibly behind a cache but not necessarily;});

Code that uses your part could access the data through part.Foo.Value.Bar, or you could also add additional just-in-time property accessors on the part to hide that detail, like: public BarData Bar {get {return Foo.Value.Bar;}}


Mar 18, 2011 at 9:47 AM

Perhaps the name is confusing me, if u say it really just wires callback's it should be named OnInitialized, which already exists hmm... OnLoading and OnLoaded gives me the idea that the part is really loading & loaded. I do understand how it works and the StorageFilter indeed use a LazyField<TRecord> and instance._record.Loader(....)

Thanks for a push into the right direction, a LazyField is really a better place for accessing a webservice when needed.

I also will be adding a statePart or something to the contentitem where information is going to be stored when the contentitem is invalidated, out of date, etc.. so in that case the data has to be refreshed.



Mar 18, 2011 at 11:30 AM

Orchard.Core.Common.Utilities LazyField vs Orchard.ContentManagement.Utilities.LazyField ?

Orchard.Core.Common.Utilities LazyField
Is only used in the CommonPart

This one has a second parameter in the Func delegate
Is used everywhere else.

I think i should use the ContentManagement one, can't those be merged into one LazyField with an overload?

Mar 18, 2011 at 12:09 PM
Edited Mar 18, 2011 at 12:54 PM

After digging a bit i think i'll write a custom Repository, or even a custom StorageFilter
The custom repository will then have the knowledge of accessing external data or the NHibernate Session.

I don't think i should dig deeper into NHibernate, using a ISessionLocator, ISessionFactory and IInterceptor.
NHibernate goes to the database and not to a webservice (or csla businessobject)

Mar 18, 2011 at 5:10 PM
Edited Mar 18, 2011 at 5:19 PM

I should start my own blog (on Orchard ofc.) and writing stuff in better english then i do here hehe.

I think i've some basics.. for using Csla business objects directly (i could do it for a IService as well, but csla is what our backend API is made from)
It's a bit sloppy atm and i did run into limitations of Lambda's (A lambda expression with a statement body cannot be converted to an expression tree)

For test i needed a dummy business object and just a random partrecord we wrote in a own module.

    public class DossierInfoTest : Csla.ReadOnlyBase<DossierInfoTest> { 
        public static DossierInfoTest GetRelatieInfo(int id) {
            return DataPortal.Fetch<DossierInfoTest>(new SingleCriteria<int>(id));

    public static class DossierInfoMapper {
        public static UserProfilePartRecord MapFromBO(DossierInfoTest bo) {
            // map bo to record
            return new UserProfilePartRecord();

This is what i made so far:


    public interface ICslaRepository<TRecord, TBusinessObject> : IRepository<TRecord> {


    public class CslaRepository<TRecord, TBusinessObject> : Repository<TRecord>, ICslaRepository<TRecord, TBusinessObject> {
        public CslaRepository(ISessionLocator sessionLocator)
            : base(sessionLocator) {

        public override void Create(TRecord entity) {
        public override IQueryable<TRecord> Fetch(System.Linq.Expressions.Expression<Func<TRecord, bool>> predicate) {
            return base.Fetch(predicate);

        public override IQueryable<TRecord> Fetch(System.Linq.Expressions.Expression<Func<TRecord, bool>> predicate, Action<Orderable<TRecord>> order) {
            return base.Fetch(predicate, order);

        public override void Update(TRecord entity) {

        public override void Delete(TRecord entity) {

Registering it in Autofac

    public class FrameworkModule : Module {
        protected override void Load(ContainerBuilder builder) {


    public class CslaStorageFilter<TRecord, TBusinessObject> : StorageFilter<TRecord> 
        where TRecord : ContentPartRecord, new()
        where TBusinessObject : Csla.ReadOnlyBase<TBusinessObject>, new() {
        public CslaStorageFilter(ICslaRepository<TRecord, TBusinessObject> repository)
            : base(repository) {

        protected override TRecord GetRecordCore(ContentItemVersionRecord versionRecord) {
            // todo: lots of checks to determine if the csla factory method should be called
            var bo = Fetch();
            var record = FetchCompleted(bo);
            return record;

            // todo: might return record data from database if checks fail
            return base.GetRecordCore(versionRecord);

        public Func<TBusinessObject> Fetch;
        public Func<TBusinessObject, TRecord> FetchCompleted;

An static helper

    public static class CslaStorageFilter
        public static StorageFilter<TRecord> For<TRecord, TBusinessObject>(ICslaRepository<TRecord, TBusinessObject> repository,
            Expression<Func<TBusinessObject>> fetchMethod,
            Expression<Func<TBusinessObject, TRecord>> fetchCompletedMethod
            where TRecord : ContentPartRecord, new()
            where TBusinessObject : Csla.ReadOnlyBase<TBusinessObject>, new()
            CslaStorageFilter<TRecord, TBusinessObject> storageFilter = new CslaStorageFilter<TRecord, TBusinessObject>(repository);
            storageFilter.Fetch = fetchMethod.Compile();
            storageFilter.FetchCompleted = fetchCompletedMethod.Compile();
            return (StorageFilter<TRecord>)storageFilter;

Callling it from the handler

            Filters.Add(CslaStorageFilter.For<UserProfilePartRecord, DossierInfoTest>(repository,
                    () => DossierInfoTest.GetRelatieInfo(this.Relatienummer),
                    (bo) => DossierInfoMapper.MapFromBO(bo)

Looking at my own code i'm not sure if i needed to write an own repository, i could just keep it at one lever higher, inside the CslaStorageFilter.. just calling the compiled lambda expressions.