August 2008 Entries

Following on from Steve's excellent post on how to copy one or more properties from one Page Type to another, I decided to share how easy it is to turn his hard work into an EPiServer plug-in so that it will appear in the admin area of the CMS.

First you need to 'decorate' (that's an official term honestly!) your page with the following GuiPlugin attribute:

[GuiPlugIn(DisplayName = "Property Duplicator", 
    Description = "Duplicate Page Type Properties", 
    Area = PlugInArea.AdminMenu, 
    Url = "~/cms/Admin/DuplicatePageTypeProperties.aspx")]

If you're not sure what that actually means, it's as simple as adding it above the Page's class definition in the code behind, I.e.

[GuiPlugIn(DisplayName = "Property Duplicator", 
    Description = "Duplicate Page Type Properties", 
    Area = PlugInArea.AdminMenu, 
    Url = "~/cms/Admin/DuplicatePageTypeProperties.aspx")]
public partial class DuplicatePageTypeProperties : System.Web.UI.Page
{
   ...

What the attribute does is tell EPiServer to add an item to the Admin Menu (under the 'Tools' heading) called "Property Duplicator" (the DisplayName) which when clicked will display the Url provided (in this case the page that Steve created).

And that's essentially it. Rebuild the project and log into the admin area and bingo there it is. Now if you stop there it will work fine, but it wont have the same 'look & feel' as the rest of EPiServer's admin area, so all that's left to do is add a reference to the admin area's css file to the <head> of the page as shown below (NOTE: you'll also need to remove the runat="server" from the <head> tag):

<link rel="stylesheet" type="text/css" 
    href="<%=EPiServer.Global.EPConfig.RootDir%>util/styles/system.css">

NOTE: The above principle can be applied to both EPiServer CMS 4 and 5 sites, however Steve's code will need to be updated to reflect the changed made in the EPiServer API in version 5.
NOTE: The Url provided in the GuiPlugin attribute will need to be updated if the page is not created at ~/cms/Admin/DuplicatePageTypeProperties.aspx 

The full code to make it easier is as follows:

DuplicatePageTypeProperties.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DuplicatePageTypeProperties.aspx.cs" Inherits="EPiServerSample.cms.admin.DuplicatePageTypeProperties" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1">
    <title>Untitled Page</title>
    <style type="text/css">
        label { font-weight: bold; color: navy; }
        select { margin-top: 0.5em; margin-bottom: 1em;}
    </style>
    <link rel="stylesheet" type="text/css" href="<%=EPiServer.Global.EPConfig.RootDir%>util/styles/system.css">
</head>
<body>
    <h1>EPiServer:  Copy Page Type Properties to Another Page Type</h1>
    <form id="form1" runat="server">
    <div style="width:40%; float:left;">
      <asp:Label ID="Label1" runat="server" AssociatedControlID="lbSourcePageType">Source Page Type:</asp:Label><br />
      <asp:ListBox Width="100%" Height="200" ID="lbSourcePageType" AutoPostBack="true" runat="server" /><br />
      <asp:Label ID="Label2" runat="server" AssociatedControlID="lbSourceProperties">Source Properties:</asp:Label><br />
      <asp:ListBox Width="100%" Height="200" ID="lbSourceProperties" SelectionMode="Multiple" runat="server" />
    </div>
    <div style="width:40%; float:left;">
      <asp:Label ID="Label3" runat="server" AssociatedControlID="lbTargetPageType">Target Page Type:</asp:Label><br />
      <asp:ListBox Width="100%" Height="200" ID="lbTargetPageType" runat="server" AutoPostBack="true" /><br />
      <asp:Label ID="Label4" runat="server" AssociatedControlID="lbTargetProperties">Target Properties:</asp:Label><br />
      <asp:ListBox Width="100%" Height="200" ID="lbTargetProperties" runat="server" />
    </div>
    <div style="clear:both; width:auto; margin-left:auto; margin-right:auto;">
        <asp:Button ID="btnCopyProperties" runat="server" OnClick="btnCopyProperties_Click" Text="Copy Properties -->" />
    </div>
    </form>
</body>
</html>

DuplicatePageTypeProperties.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using EPiServer.PlugIn;

namespace EPiServerSample.cms.admin
{
    [GuiPlugIn(DisplayName = "Property Duplicator", Description = "Duplicate Page Type Properties", Area = PlugInArea.AdminMenu, Url = "~/cms/Admin/DuplicatePageTypeProperties.aspx")]
    public partial class DuplicatePageTypeProperties : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                EPiServer.DataAbstraction.PageTypeCollection p = EPiServer.DataAbstraction.PageType.List();

                lbSourcePageType.DataSource = p;
                lbSourcePageType.DataValueField = "ID";
                lbSourcePageType.DataTextField = "Name";
                lbSourcePageType.DataBind();

                lbTargetPageType.DataSource = p;
                lbTargetPageType.DataValueField = "ID";
                lbTargetPageType.DataTextField = "Name";
                lbTargetPageType.DataBind();
            }

            lbSourcePageType.SelectedIndexChanged +=
                new EventHandler(this.lbPageType_SelectedIndexChanged);
            lbTargetPageType.SelectedIndexChanged +=
                new EventHandler(this.lbPageType_SelectedIndexChanged);

            btnCopyProperties.Enabled =
                (lbSourcePageType.SelectedIndex != -1) &&
                (lbTargetPageType.SelectedIndex != -1);

        }

        protected void lbPageType_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox lb = (ListBox)sender;
            ListBox lbp = null;

            if (object.ReferenceEquals(lb, this.lbSourcePageType)) lbp = lbSourceProperties;
            if (object.ReferenceEquals(lb, this.lbTargetPageType)) lbp = lbTargetProperties;

            lbp.Items.Clear();

            if (!String.IsNullOrEmpty(lb.SelectedValue))
            {
                EPiServer.DataAbstraction.PageType pt = EPiServer.DataAbstraction.PageType.Load(int.Parse(lb.SelectedValue));
                lbp.DataSource = pt.Definitions;
                lbp.DataTextField = "Name";
                lbp.DataValueField = "ID";
                lbp.DataBind();
            }
        }


        protected void btnCopyProperties_Click(object sender, EventArgs e)
        {
            int[] selectedIndices = lbSourceProperties.GetSelectedIndices();
            if (selectedIndices.Length == 0) return;

            EPiServer.DataAbstraction.PageType source =
                EPiServer.DataAbstraction.PageType.Load(int.Parse(lbSourcePageType.SelectedValue));
            EPiServer.DataAbstraction.PageType target =
                EPiServer.DataAbstraction.PageType.Load(int.Parse(lbTargetPageType.SelectedValue));


            foreach (int selectedIndex in selectedIndices)
            {
                EPiServer.DataAbstraction.PageDefinition sdef =
                    EPiServer.DataAbstraction.PageDefinition.Load(int.Parse(
                        lbSourceProperties.Items[selectedIndex].Value));

                EPiServer.DataAbstraction.PageDefinition tdef = new EPiServer.DataAbstraction.PageDefinition();
                tdef.PageTypeID = target.ID;
                tdef.DefaultValueType = sdef.DefaultValueType;
                tdef.DefaultValue = sdef.DefaultValue;
                tdef.EditCaption = sdef.EditCaption;
                tdef.FieldOrder = target.Definitions.Count;
                tdef.HelpText = sdef.HelpText;
                tdef.LanguageSpecific = sdef.LanguageSpecific;
                tdef.LongStringSettings = sdef.LongStringSettings;
                tdef.Name = sdef.Name;
                tdef.Required = sdef.Required;
                tdef.Searchable = sdef.Searchable;
                tdef.Tab = sdef.Tab;
                tdef.Type = sdef.Type;

                tdef.PageTypeID = target.ID;
                tdef.Save();
                target.Definitions.Add(tdef);
                target.Save();

            }
            EPiServer.DataAbstraction.PageType.ClearCache();

            lbPageType_SelectedIndexChanged(lbTargetPageType, new EventArgs());
        }
    }
}

Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I've just installed EPiServer Mail into an EPiServer CMS 5 SP2 site that is running under .NET 3.5 (yes i know its not officially supported but hey). Much to my annoyance I had 3 errors to fix - which simply meant removing 3 lines from the web.config that either the EPiServer Mail install (or the hotfix) added. The offending lines which must be removed are as follows:

<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I've just spent too long trying to upgrade EPiServer CMS 5 to SP2 but kept getting the following error:

Login failed for user ''. The user is not associated with a trusted SQL Server connection.

Turns out the problem was that EPiServerManager was pulling the connection string out of my web.config, but it appears it was ignoring the fact it specified an Integrated/Windows connection and was passing an empty SQL username to the database - hence the empty quote marks above. (cheers for your help Steve!)

Solution: Temporarily change the SQL connection string in the site's web.config to use an SQL username/password, perform the update and change the string back.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist