Join us this Friday for AI in Action at the Virtual Happy Hour! This free virtual event is open to all—enroll now on Academy and don’t miss out.

 

Trouble creating local block programmatically

Vote:
 

Hi,

I'm having troubles creating a local block programmatically to a page. This is a simplified example:

var newPage = _contentRepository.GetDefault(parent).CreateWritableClone();

newPage.Name = "MyName";
newPage.LocalBlock = CreateBlock();

_contentRepository.Save(newPage, SaveAction.Publish, AccessLevel.NoAccess);

private MyBlock CreateBlock()
{
    var block = new MyBlock();
    block.MainBody = new XhtmlString("MyMainBody");
    return block;
}

The above code doesn't work. The MainBody-property for MyBlock always end up empty.

I have managed to find a way which works:

var newPage = _contentRepository.GetDefault(parent).CreateWritableClone();

newPage.Name = "MyName";
newPage.LocalBlock.MainBody = new XhtmlString("MyMainBody");

_contentRepository.Save(newPage, SaveAction.Publish, AccessLevel.NoAccess);

But this way isn't so practical. In my case I have several block properties on several different page types which I want to create programmatically. So it would be alot of duplicated code. Why doesn't the first way work? Is there a way to make it work?

Thanks in advance

Anders

#122246
May 28, 2015 14:43
Vote:
 

Hello Anders

Have you considered an EPiServer intialization module? This should allow you to hook into the LoadedDefaultContent event and set your default properties on your local blocks apppropriately. 

David

#122247
May 28, 2015 15:02
Vote:
 

Thanks for your answer David. It doesn't solve my problem though. Every page I'm creating has unique property values in their blocks so it's not default values. Or am I misunderstanding you?

Anders

#122248
May 28, 2015 15:07
Vote:
 

Hello Anders

I assume your values can be worked out programmatically? If so then the following should/could work:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class DefaultBlockProperties : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
        contentEvents.LoadedDefaultContent += contentEvents_LoadedDefaultContent;
    }

    void contentEvents_LoadedDefaultContent(object sender, ContentEventArgs e)
    {
        if (e.Content is YourPageType || e.Content is SomeOtherPageType) //etc
        {
            //Do your work to populate your default property here
        }
    }


    public void Preload(string[] parameters) { }

    public void Uninitialize(InitializationEngine context) { }
}

You can also implement an interface on the page(s) that have the local block to simplify the access to the block if you want to make things more elegant.

#122249
Edited, May 28, 2015 15:13
Vote:
 

An InitModule is not an option since we need to run our service with different parameters and we also don't want it to run on Application_Start. 

According to the following link, what I want to accomplish doesn't seem possible: http://joelabrahamsson.com/working-programmatically-with-local-blocks-in-episerver-7/

#122251
May 28, 2015 15:27
Vote:
 

Hello Anders

The initialisaton module runs at application start, however the code I supplied sets up a handler to listen out for EPiServer content events, so the code in the contentEvents_LoadedDefaultContent method will ran after a content item has been created.

David

#122254
May 28, 2015 15:54
Vote:
 

Believe me, this wont work in this specific case :) I don't really have time sitting here describing all the requirements so you just have to take my word for it :) But thank you anyway.

I ended up doing something like this instead:

var newPage = _contentRepository.GetDefault<MyPage>(parent).CreateWritableClone();

newPage.Name = "MyName";
var myBlock = CreateBlock();
newPage.LocalBlock.MainBody = myBlock.MainBody;

_contentRepository.Save(newPage, SaveAction.Publish, AccessLevel.NoAccess);

private MyBlock CreateBlock()
{
    var block = new MyBlock();
    block.MainBody = new XhtmlString("MyMainBody");
    return block;
}

The number of code lines in my class increased quite a lot but atleast I still can use external methods for creating the different blocks.

#122256
Edited, May 28, 2015 16:04
* 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.