Tuesday, February 24, 2009

EPiServer Mail 4.4 Released

Last Friday, the 20th February, the new version of EPiServer Mail was released! This release has the version number 4.4 and brings some long awaited features.

The first and maybe the best news is that EPiServer Mail now works with EPiServer CMS R2 SP1 and EPiServer CMS R1 SP3. This also means that the version of System.Web.Extensions that is being used is now 3.5. I think a lot of our partners will be happy about this since most of them are using the 3.5 version.

The installation process have of course also been updated and now it uses the Deployment Center just like the CMS and the Relate+ package – installation has never been easier. Speaking about Relate+; the release of EPiServer Mail 4.4 means that now the packaging of Relate+ is complete, since Mail is one of the included components of the packaging.

With this new version of Mail the integration with the CMS has also been made tighter. First of all the look and feel has been updated to better blend in together with the CMS (see screenshot). But also it is now possible to send a CMS page directly from the Edit mode without having to go to Mail. But there is more; a new feature lets you group newsletters under one node in the page tree and see an overall trend graph of the entire collection. Pretty cool!

EPiServerMail_update_admin

Together with the release of EPiServer Mail came a hotfix for EPiServer Common. This is the common framework used by both Mail and Community. The hotfix includes a new integration membership provider that works like the Multiplexing Membership Provider that comes with the CMS. I think this is a very welcome feature, especially for our enterprise customers.

What are you waiting for? Head over to the download section of EPiServer World and get your copy of the new EPiServer Mail.

For the complete list of new features have a look at this article by Product Manager Per Ivansson.

Monday, February 16, 2009

EPiServer Day 2009 and The EPiServer Awards

I want to take the opportunity to post a promotion for the upcoming EPiServer Day 2009, which will take place on the 10th and 11th of March. It will be two days with loads of presentations, seminars, debates and mingling with EPiServer and our partners. So to all of you EPiServer fans and also to all of you who are not hooked yet, head over to the registration page and sign up for two great days of “The Engaged Web”.

I will of course attend the entire event. Please feel free to join my seminar “Att utveckla ett Online Community” (in Swedish)  on the 10th of March. In this session I will primarily focus on the difference between developing a standard CMS site compared to developing a community site.

I will also give a talk on day two, “Community Page Provider” (in Swedish). This time I will team up with Johan Björnfot and talk about how you could utilize the Page Provider concept of EPiServer CMS together with EPiServer Community. To all developers joy we will spend more time in Visual Studio than PowerPoint in this session.

A final note, if you chose to go the event don’t miss out on The EPiServer Awards, that will be presented at the dinner held at Clarion Hotel Stockholm. This year there were the record breaking number of 118 nominations to the award, be prepared to see some awesome web projects based on EPiServer!

Friday, February 13, 2009

Installing EPiServer Community standalone

When installing the standalone version of EPiServer Community, or actually when installing any version of EPiServer Community on a IIS 7 there is a small glitch in the Web.config that is installed. But the glitch will only be a problem in the standalone version.

If you install the site with the default settings you will be able to reach the administration interface by accessing http://localhost:17000/EPiServerCommunity. This will however result in the following error:

[NullReferenceException: Object reference not set to an instance of an object.]
   EPiServer.Common.Settings.get_DefaultSecurity() +29
   EPiServer.Community.Web.Administration.CommunityModule.context_AcquireRequestState(Object sender, EventArgs e) +9
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +79
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +170

The is due to the glitch I mentioned, more specifically the attribute preCondition="managedHandler" is lacking from the EPiServerCommunity module section in the Web.config. The obvious fix is to add this attribute. After you have done this you will end up with something like this:

<modules>
   <add name="EPiServerCommon" type="EPiServer.Common.Web.HttpModule, EPiServer.Common.Web" preCondition="managedHandler" />
   <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="managedHandler" />
   <add name="EPiServerCommunity" type="EPiServer.Community.Web.Administration.CommunityModule, EPiServer.Community.Web.Administration" preCondition="managedHandler" />
</modules>

And now your standalone EPiServer Community site will rock!

Tuesday, February 3, 2009

Browser Upload Performance

A while back, when the EPiServer Community team was tweaking the performance of our Video Service, we found some weird facts about upload performance of different browsers. Especially about our beloved Firefox, which is my own personal favorite in the browser jungle.

The Video Service is delivered as a SaaS solution to our end-customers. The videos the users of the site upload is decoded, stored in and delivered from a custom built solution implemented in Amazon EC2 and Amazon S3. A great deal of the user experience is the time it takes for a user from picking the file to upload to seeing the video on the site. This includes some steps:

  1. Posting the file to Amazon
  2. Encoding the file to a Flash movie
  3. Notify the web site that video is ready for delivery

Since a significant part of this time is spent in step 1, the upload performance of the web browser is of great importance for the complete user experience. When testing the Video Service with different browsers we noticed that Firefox seemed to have a poor upload performance compared to other browsers. So, we decided to dig into this and do some more extensive testing.

The Tests

The tests were performed by creating a simple form (see below) that post to a page called uploadtest.php, which did nothing with the posted data. We timed the upload the old fashion way by using a stop watch. One may argue that this can not be that accurate, but considering we were using pretty large files and the tests were repeated several times we believe that any timing error caused by manual timing is negligible in comparison to the massive difference in upload time – especially since we were not after the absolute figures, rather we wanted to see the relationship in performance between different browsers and platforms.

<html>
    <body>
        <form method="post" enctype="multipart/form-data" action="uploadtest.php">
            <input type="file" name="data">
            <input type="submit">
        </form>
    </body>
</html>

Since we wanted to see if there were any difference depending on the file size, we performed the tests with two different files. In the first test case we used a file with size 9 307 242 bytes.

upload_comparison_small_file 
As you can see from the chart above Firefox is out-performed by all of the other players. Note that on Windows, Google Chrome and IE is four times as fast as Firefox. Safari is better than Firefox, but still a long way behind the leaders. We couldn’t believe our own eyes, so we turned to a test case with a larger file. This time the file size was 31 457 280 bytes.

upload_comparison_large_file
The results on Windows are about the same as the previous test case, but Firefox on Ubuntu and Mac OS X seems to be on steroids. Safari has also significant better performance on Mac OS X with the bigger file.

Our main concern with these results were Firefox, since it is more common than Safari. With the performance, or really lack of performance, that Firefox showed in these test we thought that something most be wrong. After spending some time chatting with different people in the official Firefox irc channel (#firefox @ irc.mozilla.org) we decided to file a bug report at Mozilla, Bug 454990. Based on the comments for this bug report, it seems like other people have experienced similar problems.

Conclusion

I’m sad to say that the conclusion from these tests must be that if you are uploading a lot of files, especially if it is large files, you should leave Firefox behind and use Internet Explorer or Chrome instead – at least for now. I sincerely hope that Mozilla will fix these performance issues in the future, so I can go back to just use my favorite browser.

Note 1: Since we made the test new versions of the browsers have been launched.

Note 2: Of course we could have included more browsers in the test, but we concentrated on the most popular once.

Monday, February 2, 2009

Selective copy with PowerShell

The other day I faced a problem where I wanted to extract a project from our TFS and sending it to one of our partners. It was a small sample project to show off how you could extend EPiServer Community and utilize the Common Framework which is included in the Community platform.

Anyway, back to the problem. Since I was going to send the entire project I wanted to exclude all the source control bindings and references, a job one could easily do manually - but that's no challenge. I thought this was a time as good as any other to learn some PowerShell. This is something I wanted to do for a long time, but haven't had the need or time.

Since I'm a PowerShell newbie, I have probably not done everything in the absolute best way, but hey it works! This is what I wanted to do:

  1. Copy all of the files excluding source control files to an export directory
  2. Delete source control bindings from the csproj file

My first thought was to use the Copy-Item commandlet to solve the first part of the problem. But it turned out that this was not ideal since this cmdlet doesn’t seem to work that well with the recurse flag set in combination with the exclude flag. So I turned to the Get-ChildItem cmdlet instead. By iterating through the files and folders I could copy the items and at the same time use Substring to find out the path to the item to enable reconstruction of the folder structure in the export folder.

Get-ChildItem 'C:\Projects\EPiServer.Community.Samples.Product' -exclude *.suo,*.vspscc,*.sln,*.vssscc -Recurse | foreach-object -process{if(!$_.Fullname.Contains("\bin") -and !$_.Fullname.Contains("\obj")) {copy-item $_.FullName -Force -destination (join-path $placeHolder $_.Fullname.Substring($_.Fullname.IndexOf("EPiServer.Community.Samples.Product")))}}
In the process I also removed both the bin folder and the obj folder.

Now to the second problem, to remove the source control bindings in the csproj file. This is actually a task of manipulating Xml, which is done by constructing a XmlDocument - the only tricky thing is to find the nodes to delete. This could be done by using XPath through the use of SelectNodes method, but one must keep in mind that when namespace is used in the XmlDocument, XPath doesn’t “just work”.

One way to make it a bit easier to work with namespaces and XPath is to install the PowerShell Community Extensions and use the Select-Xml method. In my simple PowerShell script I wanted to avoid the use of external scripts, so I used the “dot-notation” to traverse the Xml instead. Since I knew exactly how the Xml looked like, this very non-generic solution worked fine.

#Filenames
$placeHolder = "C:\tmp\export"
$csprojName = "EPiServer.Community.Samples.Product.csproj"
$csprojFile = join-path $placeHolder "EPiServer.Community.Samples.Product\EPiServer.Community.Samples.Product.csproj"
$csprojFileTmp = join-path $placeHolder "EPiServer.Community.Samples.Product\EPiServer.Community.Samples.Product.csproj_tmp"
 
#Read the project file as XML
$proj = [xml](Get-Content $csprojFile)
 
$nodes = $proj.Project.PropertyGroup[0].GetElementsByTagName("SccProjectName")
$proj.Project.PropertyGroup[0].RemoveChild($nodes.Item(0))
 
$nodes = $proj.Project.PropertyGroup[0].GetElementsByTagName("SccLocalPath")
$proj.Project.PropertyGroup[0].RemoveChild($nodes.Item(0))
 
$nodes = $proj.Project.PropertyGroup[0].GetElementsByTagName("SccAuxPath")
$proj.Project.PropertyGroup[0].RemoveChild($nodes.Item(0))
 
$nodes = $proj.Project.PropertyGroup[0].GetElementsByTagName("SccProvider")
$proj.Project.PropertyGroup[0].RemoveChild($nodes.Item(0))
 
#Save file
$proj.Save($csprojFileTmp)
 
#Remove old file
Remove-Item $csprojFile
 
#Rename tmp file
Rename-Item -Path $csprojFileTmp -NewName $csprojName
Problem solved!