Tuesday, February 21, 2012

Webparts in EPiServer: Step by step

At Epinova we’re huge fans of using web parts in EPiServer as this enables the editor to choose what type of content should be displayed on certain pages while at the same time ensuring the editor doesn’t try to break the design of the website.

This is a step by step guide to getting started with web parts in EPiServer using the AlloyTech demo site as an example.

Our goal is to transform the bottom region of the AlloyTech startpage (the pink rectangle) into a web part zone where the editor can choose between several web parts.

AlloyOriginal_2

1) Install EPiCode.WebParts.Core and Epinova.WebParts.Providers from the EPiServer Nuget feed.

NugetInstall

2) Make sure a reference has been added to the following dlls in your project:

EPiCode.WebParts.Core.dll
Epinova.WebParts.Providers.dll
Microsoft.Web.Preview.dll

3) In MasterPage.Master, add a ScriptManagerLowUiImpact control and a EPiWebPartManager control after the opening <form> tag:

1: <form runat="server">

2:    <epicode:ScriptManagerLowUiImpact runat="server" EnablePartialRendering="false" />

3:    <epicode:EpiWebPartManager runat="server" Personalization-InitialScope="Shared" Personalization-Enabled="true" />

4:    <!-- Your markup here -->

5: </form>

4) Create a ManagementConsole.ascx:

Note that the ManagementConsole.ascx file should NOT have a code-behind or designer file, instead it should inherit directly from System.Web.UI.UserControl.

1: <%@ Control Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.UserControl" %>

2:  

3: <epicode:WebPartManagementConsole ID="WebPartManagementConsole1" runat="server" />

4: <asp:CatalogZone runat="server" ID="ThemeCatalogZone">

5:    <ZoneTemplate>

6:       <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1" runat="server">

7:          <WebPartsTemplate>

8:          </WebPartsTemplate>

9:       </asp:DeclarativeCatalogPart>

10:    </ZoneTemplate>

11: </asp:CatalogZone>

What you’ve done here is to declare a CatalogZone called ThemeCatalogZone, and later you will declare the different type of web parts available in this zone by adding them to the WebPartsTemplate.

5) Add the following to the <pages><control> section of your web.config file:

<add tagPrefix="uc" tagName="ManagementConsole" src="~/Templates/AlloyTech/WebParts/Util/ManagementConsole.ascx" />

6) Add the ManagementConsole usercontrol to your MasterPage.Master (directly after the EPiWebPartManager control):

1: <form runat="server">

2:    <epicode:ScriptManagerLowUiImpact runat="server" EnablePartialRendering="false" />

3:    <epicode:EpiWebPartManager runat="server" Personalization-InitialScope="Shared" Personalization-Enabled="true" />

4:    <uc:ManagementConsole runat="server" />

5:    <!-- Your markup here -->

6: </form>

7) Create a banner webpart:

A banner web part will consist of an image, an alternative text and a URL for the image. Create a usercontrol called BannerPart, and add the following code to BannerPart.ascx.cs:

1: public partial class BannerPart : UserControlWebPartBase

2: {

3:    [Personalizable, IsRequired]

4:    public PropertyImageUrl Image { get; set; }

5:  

6:    [Personalizable]

7:    public PropertyString ImageAltText { get; set; }

8:  

9:    [Personalizable, IsRequired]

10:    public PropertyUrl ImageLink { get; set; }

11:  

12:    public BannerPart()

13:    {

14:       Image = new PropertyImageUrl();

15:       ImageAltText = new PropertyString();

16:       ImageLink = new PropertyUrl();

17:    }

18:  

19:    protected override void OnPreRender(EventArgs e)

20:    {

21:       uxImage.ImageUrl = Image.Value != null ? (string)Image.Value : string.Empty;

22:       uxImage.AlternateText = ImageAltText.Value != null ? (string)ImageAltText.Value : string.Empty;

23:       uxLink.NavigateUrl = ImageLink.Value != null ? (string) ImageLink.Value : string.Empty;

24:    }

25: }

Here we have declared the three properties mentioned above: Image, ImageAltText and ImageLink. All the properties are Personalizable, but only Image and ImageLink are required.

Add the following markup to BannerPart.ascx:

1: <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="BannerPart.ascx.cs"

2: Inherits="EPiServer.Templates.AlloyTech.WebParts.BannerPart" %>

3:  

4: <asp:HyperLink ID="uxLink" runat="server">

5: <asp:Image ID="uxImage" runat="server" /></asp:HyperLink>

You can add translations to your Banner web part by creating a lang file called WebParts.xml:

1: <?xml version="1.0" encoding="utf-8" ?>

2:    <languages>

3:       <language name="English" id="en">

4:          <webparts>

5:             <webpart name="BannerPart">

6:                <caption>Banner</caption>

7:                <description>Image banner with link and alternative text</description>

8:             </webpart>

9:             <common>

10:               <property name="Image">

11:                 <caption>Image</caption>

12:                 <help></help>

13:               </property>

14:               <property name="ImageAltText">

15:                 <caption>Alternative Text</caption>

16:                 <help></help>

17:               </property>

18:               <property name="ImageLink">

19:                 <caption>Image Link</caption>

20:                 <help></help>

21:               </property>

22:             </common>

23:          </webparts>

24:      </language>

25: </languages>

7) Add BannerPart to the <WebPartsTemplate> in ManagementConsole.ascx:

1: <%@ Control Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.UserControl" %>

2: <%@ Register TagPrefix="uc" tagName="BannerPart" src="../BannerPart.ascx" %>

3:  

4: <epicode:WebPartManagementConsole ID="WebPartManagementConsole1" runat="server" />

5: <asp:CatalogZone runat="server" ID="ThemeCatalogZone">

6:    <ZoneTemplate>

7:       <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1" runat="server">

8:           <WebPartsTemplate>

9:              <uc:BannerPart ID="wpBanner" runat="server" />

10:          </WebPartsTemplate>

11:      </asp:DeclarativeCatalogPart>

12:    </ZoneTemplate>

13: </asp:CatalogZone>

8) Add a webpart zone in your Default.aspx file:

<epicode:ZoneLowUiImpact runat="server" ID="MainContentAreaZone" catalogzoneid="ThemeCatalogZone" layoutorientation="Horizontal" />

Note that the CatalogZoneId is equal to the ID of the CatalogZone in step 7, which means that the editor will be able to create a Banner webpart on the startpage.

9) Create a banner webpart on the startpage of your website:

In order to do this you need to be logged in as an administrator. If you right-click your startpage in view mode, you will see a new option in the context menu called “Edit Web Parts”. Clicking this option will show you an overview of the web part zones on the page:

WebpartZone

You will also see a dropdown list containing all the available web parts for this web part zone, in this case only Banner. Click “Add” and you will be able to create a Banner web part:

AddWebPart

Fill in all the properties and clicking OK will give you a preview of the web part on the page. If you want to publish your new web part, right-click the page and chose “Save and publish”.

10) Create your own web parts:

If you want to create more webparts you need to create a usercontrol for your webpart inheriting from UserControlWebPartBase as explained in step 7. You will also need to add it to the <WebPartsTemplate> of your ManagementConsole.ascx file in order for the administrator to access it in the web part zone.

18 comments:

  1. A question? What are some reason's why someone would use EPiServer over SharePoint?

    ReplyDelete
    Replies
    1. Price?
      Right tool for the job - at least web publishing?

      Delete
    2. SharePoint covers a very wide range of business needs; WCM is just one vertical. On the surface it would make sense to leverage SharePoint for WCM if the business has already implemented it in other areas. In reality, we rarely ever leverage the existing SharePoint infrastructure for WCM sites. Server configurations, security and scaling for consumer facing sites inevitably drive a new infrastructure and WCM builds become fractured from the original intent.

      While EPiServer can play additional roles, it is incredibly strong for creating content managed solutions for our clients in the WCM space that SharePoint plays in. It is a much more affordable offering than SharePoint in almost every configuration. From a developer standpoint I can also confidently state that our team has a much higher satisfaction with EPiServer than SharePoint which leads to quicker development and cheaper implementations.

      Delete
    3. I'm not an expert on Sharepoint, but the general rule is: If a customer is wondering whether to use EPiServer OR Sharepoint, the customer is asking himself the wrong question. The question they should ask themselved instead is "What is the purpose of our site?". I recommend checking out this blog post by Daniel Berg as he sums it up quite clearly: http://blog.bergdaniel.se/post/EPiServer-CMS-or-SharePoint.aspx

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Great article. I've used webparts in other, non-epi projects, before but always hit a wall because they do not work in FireFox, is this solution cross browser compliant?

    ReplyDelete
    Replies
    1. Thank you! And yes, this solution is cross browser compliant :) If you're interested in how that has been done, you can check out these blog posts: http://www.epinova.no/blog/Thomas-Leela/tags/webparts/

      Delete
  4. Great post!
    Do you have any experience upgrading a CMS site with webparts from 5 to 6 R2?

    ReplyDelete
    Replies
    1. Thanks :) I've upgraded plenty of EPiServer CMS 5 sites to CMS 6 R2 without problems. As long as you remember to upgrade to the latest version of EPiCode.WebParts.Core.dll and Epinova.WebParts.Providers.dll, you'll be fine.

      Good luck with the upgrade!

      Delete
  5. Great post!
    I tried to implement the steps above in several EPiServer projects, but I always end up with a "Sys is undefined" message.
    This can be resolved by adding an asp:ScriptManager to the page, but according to this blog that is not necessary.
    http://www.epinova.no/blog/Thomas-Leela/dates/2012/1/reducing-number-of-request-and-page-size-when-using-web-parts-in-episerver/

    I'm using the latest version of EPiCode.WebParts.Core.dll and Epinova.WebParts.Providers.dll

    Any ideas on this?

    ReplyDelete
    Replies
    1. Hi Mark,

      Thank you!
      You are correct, the asp:ScriptManager control is not necessary (unless you need it for other purposes) as long as you remember to add the epicode:ScriptManagerLowUiImpact control. Do you still get the "Sys is undefined" error when adding a ScriptManagerLowUiImpact control?

      Karoline

      Delete
    2. Hi Karoline,
      Yes I did add the epicooide:ScriptManagerLowUiImpact control, exactly as in your blogpost. I keep getting the "Sys is undefined" message.
      I debugged the epicode:ScriptManagerLowUiImpact control to see what is causing the problem. The base.OnInit() method is never called since WebPartUtil.IsUserAllowedToEditWebParts()is always false. So the scriptmanager is never initialized.

      Is this a bug in the ScriptManagerLowUiImpact or am I doing something wrong?

      Thanks for the support!

      Mark

      Delete
    3. Hm, it sounds like the user you're logged in with lacks the necessary access rights. Can you check that the roles in the section of your web.config are correct?

      Delete
    4. The user I'm logged in with is a local administrator on the machine and also an administrator in EPi.
      But you're right about the access rights. As soon as I login the message starts popping-up.

      The roles section in the web.config seems fine.

      I just don't know which extra access rights I can give to an administrator :)

      Delete
    5. I did some more debugging:
      In the epicode:ScriptManagerLowUiImpact OnInit there is a call to WebPartUtil.IsUserAllowedToEditWebParts()
      The IsUserAllowedToEditWebParts() method checks if there is a WebPartManager available on the page. But there is not, the currentWebPartManager is always null.

      Now if you put the epicode:EpiWebPartManager before the epicode:ScriptManagerLowUiImpact in the masterpage everything works as expected. Because now a WebPartManager is initialized before the ScriptManagerLowUiImpact uses it.

      Does this sound familiar?
      Thanks again for helping me out!

      Delete
    6. Huh, I actually wasn't aware of that. Thanks for pointing that out, and I'm glad you were able to make it work :)

      Delete