Blog posts by Jarle Friestad2011-04-01T22:33:20.0000000Z/blogs/Jarle-Friestad/Optimizely WorldModifing the sql command objects in EPiServer Communityhttp://www.jarlef.com/post.aspx?id=319df2bb-4b2b-4287-a563-f83d7592c7862011-04-01T22:33:20.0000000Z<p>I recently had an issue with command timeouts with an EPiServer Community site. The community database is quite large and I had a batch import job that added new entities. During some large maintaince queries on  the database that results in locking of the tables, some timeouts occurred in that period. The Community API uses the default timeout which is 30 seconds and there is no buildt in way of changing this with some sort of configuration. To overcome this issue I added the following fix.  </p> <p>EPiServer Community 4.0 uses the DatabaseHandler, located in the common framework. I was somewhat surprised to see that this class has both a public instance property as well as public virtual methods. One of these methods is the GetCommand method which have overriden with the following code.</p> <pre class="language-csharp"><code>public class MyDatabaseHandler : EPiServer.Common.Data.DatabaseHandler
{
public override System.Data.Common.DbCommand GetCommand(bool inTransaction,
string sp,
System.Data.CommandType commandType,
params object[] args)
{
var command = base.GetCommand(inTransaction, sp, commandType, args);
command.CommandTimeout = 1800;
return command;
}
}</code></pre>
<p> </p>
<p>Then simply create a EPiServer Community module that instanciates and sets the current DatabaseHandler to our custom db handler.</p>
<pre class="language-csharp"><code>public class DatabaseModule : IModule
{
public string UniqueName
{
get { return Name; }
}
public string AdministrationControl
{
get { return ""; }
}
public string Name
{
get { return "RelatePlusDatabaseModule"; }
}
public void OnApplicationStart(CommunityContext context)
{
EPiServer.Common.Data.DatabaseHandler.Instance = new MyDatabaseHandler();
}
}</code></pre>ComposerBuilder - Making composer development less painfulhttp://www.jarlef.com/post.aspx?id=faebf24a-6855-459d-b883-20cbb1074bff2011-03-08T00:00:00.0000000Z<p>I've never touched EPiServer Composer until last week, and now that I'm used to develop my EPiServer sites using PageTypeBuilder, there was quit a painful transition. Clicky clicky, enter some info, click some more, check if it works, can't drag it in, click some more and so on. And then you must do the same sequence for your test and production environment. To much configuration and no way of synchronizing these settings between the different environments make this prone to errors/human mistakes. I've added a quick little library to solve this and it based on Joel Abrahamsson's PageTypeBuilder framework.</p>
<h1>Getting the library</h1>
<p>You can find the <a href="https://github.com/jarlef/ComposerBuilder">source code</a> at github or download the <a href="https://github.com/downloads/jarlef/ComposerBuilder/ComposerBuilder.dll">binary</a> here. Just add a reference to the ComposerBuilder.dll along with your PageTypeBuilder and EPiServer Composer dlls.</p>
<p><strong>NB The currently project is still in a early stage. You might want to try this in a demo project to ensure nothing bad happens <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://www.jarlef.com/image.axd?picture=wlEmoticon-smile_1.png" alt="Smilefjes" /></strong></p>
<h1>Creating composer pages</h1>
<p>The process of creating episerver composer page is very similar as creating episerver page types using PageTypeBuilder. Instead of creating a typed pagetype that inherits from TypedPageData, you create a ExtensionsPageData object like this.</p>
<pre class="language-csharp"><code>[ExtensionPageType("1AB03438-55BE-4269-80CD-0C07A0159175",
Name = "Composer Wide Page",
Description = "A wide composer page",
Filename = "~/Composer/Pages/PageWide.aspx")]
public class PageWidePageData : ExtensionPageData
{
[ComposerArea]
public virtual string MainArea { get; set; }
}</code></pre>
<p> </p>
<p>Notice the ComposeArea properties. Since Composer by default runs http get request to the pages to discover areas on the page, this method can not be used when using pagetypebuilder since the site is not started yet.</p>
<p>The extension page it self inherits from the ExtensionPage type with the pagetype as a generic type argument like this</p>
<pre class="language-csharp"><code>public partial class PageWide : ExtensionPage<PageTypes.PageWidePageData>
{
}</code></pre>
<p>In the markup of PageWide.aspx you place you Extension Areas controls where you want the functions to the be placed.</p>
<pre class="language-xml"><code><%@ Page Language="C#" AutoEventWireup="false"
MasterPageFile="~/Templates/Masterpages/Site.master"
CodeBehind="PageWide.aspx.cs" Title="Untitled Page"
Inherits="Demo.Composer.Pages.PageWide" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<div style="min-height:100px;">
<Extension:ExtensionContentArea runat="server"
ID="MainArea" Description="MainArea"/>
</div>
</asp:Content></code></pre>
<p> </p>
<div class="bar">
<table border="0" cellspacing="0" cellpadding="2" width="588">
<tbody>
<tr>
<td width="295" valign="top"><a href="http://www.jarlef.com/image.axd?picture=image_thumb11.png"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image_thumb11" src="http://www.jarlef.com/image.axd?picture=image_thumb11_thumb.png" border="0" alt="image_thumb11" width="273" height="234" /></a></td>
<td width="291" valign="top">The extension page should now be show up as a composer pagetype when creating a new page.</td>
</tr>
</tbody>
</table>
</div>
<p> </p>
<h1> </h1>
<h1>Creating composer functions</h1>
<p>Creating the composer functions is a just another pagetype, the process of creating them is done in a similar maner. First you need to create the function type like this</p>
<pre class="language-xml"><code>[FunctionType("16126D47-0ABE-4EEB-809D-9795A03A64BA",
Name = "Test", Description = "My Test Function",
Filename = "~/Composer/Functions/TestFunction.ascx",
AvailableOnPages = AvailableOn.Specific,
AvailableOnPageTypes = new [] { typeof(PageTypes.PageWidePageData) },
AvailableOnContent = AvailableOn.All)]
public class TestFunctionData : FunctionData
{
[ComposerProperty(EditCaption = "Text")]
public virtual string Text { get; set; }
}</code></pre>
<p>This class creates a new function pagetype named "Test" and points to corresponding function usercontrol. The functions rules are defined using the AvaiableOnXXX properties. This examples makes this function only available on the page wide pagetype + all content functions that contains composer areas. The function properties is defined using the CompserPropertyAttribute. This attribute creates a corresponding episerver property for the function. In this case an xhtml text.</p>
<p><strong>NB The current release copies the default function security to every function by default.</strong></p>
<p>The next is to create the function itself; the TestFunction.ascx. The codebehind should be modified to inherit from ContentFunction class passing inn the function type.</p>
<pre class="language-xml"><code>public partial class TestFunction : ContentFunction<FunctionTypes.TestFunctionData>
{
}</code></pre>
<p>Now simply print out the xhtml using the typed property like this:</p>
<pre class="language-xml"><code><%= CurrentPage.Text %> </code></pre>
<p> </p>
<div class="bar">
<table border="0" cellspacing="0" cellpadding="2" width="608">
<tbody>
<tr>
<td width="261" valign="top"><a href="http://www.jarlef.com/image.axd?picture=image_thumb1.png"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image_thumb1" src="http://www.jarlef.com/image.axd?picture=image_thumb1_thumb.png" border="0" alt="image_thumb1" width="233" height="224" /></a></td>
<td width="345" valign="top">To complete the example we can now see the "test" function in the composer toolbox.</td>
</tr>
</tbody>
</table>
</div>
<p> </p>
<p> </p>
<p><a href="http://www.jarlef.com/image.axd?picture=image_thumb8.png"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image_thumb8" src="http://www.jarlef.com/image.axd?picture=image_thumb8_thumb.png" border="0" alt="image_thumb8" width="625" height="365" /></a></p>Polling your communityhttp://www.jarlef.com/2010/03/03/polling-your-community/2010-03-03T23:26:09.0000000ZEPiServer Community contains a lot of features, even more that is exposed in the templates delivered in the Relate+ package. One “hidden” gems is the poll feature. Here is little introduction example on how to create  simple polls, vote and display the result using the Community API.
1. Creating the Poll
To register a new poll simple [...]Sharing templates and plugins between projectshttp://www.jarlef.com/2010/02/12/sharing-templates-and-plugins-between-projects/2010-02-12T01:25:18.0000000ZOn large projects you often want/need to reuse as much of you code as possible. This also include EPiServer Templates and Plugins. This is not always as easy with web projects. You could package them as modules that you install with the deployment center but this is not as agile for templates and plugins that [...]Cross server eventshttp://jarlef.wordpress.com/2009/11/15/cross-server-events/2009-11-15T15:39:52.0000000ZThe Events Management System is a powerful feature new feature introduced in EPiServer CMS and is part of the public EPiServer API. It’s based on WCF and broadcast message between servers in the same network using UDP (or TCP). These events is mainly used to send cache update events between the servers. The Events Management [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jarlef.wordpress.com&blog=6733113&post=86&subd=jarlef&ref=&feed=1" />Google Analytics Gadget/blogs/Jarle-Friestad/Dates/2009/11/Google-Analytics-Gadget/2009-11-02T09:51:51.0000000Z<p>Here is another little contribution to the <a href="http://world.episerver.com/Download/EPiServer-CMS-6-Gadget-Contest-2009/">Gadget Contest 2009</a>. I was not sure what i was going to make util today when i discovered the <a href="http://code.google.com/apis/analytics/docs/gdata/gdataDeveloperGuide.html">Google Analytics Export API</a>. The API let you export statistics recorded from <a href="http://www.google.com/analytics/">Google Analytics</a> javascript and use them in you own application. Be ware of that the Export API is still its early beta phase and may change with time. But still, fun to play with :-)</p> <p>One thing that i know web editors like is to track their users. How many users, where they are, what they visit, what browser etc they use. Gadgets are a prefect whay of displaying this kind of information. I could make one big godly where they could choose between different reports. But i thought, the less the users need to configure the better. So i desided to splitt the reports into different gadgets. The editor could then just add the wanted reports into the dashboard. </p> <p><a href="/link/c954f1d0327e46dba6381265cf5fb1ee.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="GadgetsOverview" border="0" alt="GadgetsOverview" src="/link/7475b3137fa440c7b650c32f1c1fc1e2.png" width="590" height="179" /></a> </p> <p>Beneath you can see a demontration of the Browser report displaying how many users use the different kind of web browsers. As you can see on the screenshot you can select data from different sites using the dropdown. The site dropdown is automagicaly populated based on the logon account for the gadget on Google Analytics. This means its not limited to the episerver site itself. The current relase of this gadget only support a basic time drill down: Today, this week, this month and this Year. Maybe a post a updated version of this gadget in the near future… </p> <p><a href="/link/78563208804b4aa8a4726a433a079d52.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="StatisticsBrowsers" border="0" alt="StatisticsBrowsers" src="/link/02bd853e2e024c7381b5ba12ad07acf2.png" width="592" height="484" /></a> </p> <p>Another cool report is the demographic report showing the visitors in a map overlay.</p> <p><a href="/link/2bc4c7cda81c43f093b2a33889cb4d64.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="StatisticsDemographics" border="0" alt="StatisticsDemographics" src="/link/c499c22ec62546f4af4211cbfc31fe9f.png" width="597" height="488" /></a>. </p> <p>By the way, all of these graphs used by this gadget is made using the <a href="http://code.google.com/apis/chart/">Google Chart API</a></p> <p><strong>For the installation:</strong></p> <p>This gadget installes as module (this seems to be a popular way of doing things lately)</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:fa813ee0-8b48-43e8-bae3-88a2912a9dd4" class="wlWriterEditableSmartContent"><p>Download the <a href="/link/c2d9d82e26c945ecb408f2ad016378f4.zip" target="_blank">installer here</a></p></div> <p>The only thing you have to do after you have installed the gadget through the EPiServer Deployment Center is to update web.config with the username and password for the Google Analytics Account</p> <p><em><appSettings> <br />   <add key="AnalyticsGadget.Username" value="username" /> <br />   <add key="AnalyticsGadget.Password" value="password" /> <br /></appSettings></em></p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:362c3414-16f5-43a5-a13e-99901009a606" class="wlWriterEditableSmartContent"><p>Download the <a href="/link/b093b76fe0a64c238219757fce625dbd.zip" target="_blank">source here</a></p></div> <p><strong>Feedback</strong></p> <p>If you have any feedback on this gadget, please don’t hesitate leaving a comment :-)</p>