Having recently been subject to a number of rounding issues in an application, we've had to take a closer look at how rounding works in the .Net framework.

It seams that when using Math.Round(), there is an overload that allows us to specify the type of rounding that is used in the form of the MidpointRounding enumeration.

 

As the Microsoft documentation will tell you, there are two possible values we can choose from:

  • ToEven: Round to the nearest even number.
  • AwayFromZero: Round to the nearest number away from zero.

This proves to be quite interesting when you start thinking about it in a little more detail.  I was generally taught at school that you usually round up to the nearest number so that 0.5 becomes 1, -4.5 becomes for and so on.  This is not the case in .Net it would seem and I find it a little surprising that it has taken me this long to notice.

If you write a little console application in Visual Studio, you can take a look at how this works:

            Console.WriteLine(
                "Value   Default   Even   FromZero"
                );
            for (decimal myValue = -2.0M; myValue < 2.0M; myValue += 0.1M)
            {
                Console.WriteLine(String.Empty.PadLeft(35,'-'));
                Console.WriteLine(
                    "{0}   {1}   {2}   {3}",
                    myValue.ToString("0.0").PadLeft(5),
                    Math.Round(myValue, 0).ToString("00").PadLeft(7),
                    Math.Round(myValue, 0, MidpointRounding.AwayFromZero).ToString("00").PadLeft(4),
                    Math.Round(myValue, 0, MidpointRounding.ToEven).ToString("00").PadLeft(8)
                    );
            }

The following table give you an idea of how these work for some values.

Value Round to Even Round Away from Zero
0.4 0 0
0.5 0 1
1.4 1 1
1.5 2 2

 

The interesting point is that the default value for Math.Round when not specified is ToEven which is not really what I would have expected.  I was also a little intrigued to find that there is not provision of a TowardsZero value.  Having a look at Wikipedia, there are numerous methods of rounding and they give a handy list of which languages make which preference.  .Net favors what Wikipedia calls 'Round-half-even', which is MidpointRounding.RoundToEven.  It's sometimes refereed to as Banker's Rounding.

This clearly is not a massive revelation, but when you start to deal with systems that need to perform calculations and correlate the results of those calculations with other, less-precise systems you should take note of how you will be rounding as checking this out early can prevent headaches later.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Wednesday, December 17 2008 at 12:41 PM by Matt Nield

I am currently working on a project where it was necessary to conditionally inject some content into certain properties on some pages. Dynamic Content didn't really help me because what I wanted to do was replace entire properties with content from a property on another page and do it in a nice way for the editor. Linking the page with a shortcut to another page didn't help me because it needed to be only a partial replace and also conditional.

Here's an example - and I know there are better ways to do this but I want an example that won't compromise the Intellectual Property of what I am actually doing :)

Lets say you have a news article at http://myepisite/News/SomeArticle. The article has a nice big image on it and you want to be able to swap the image out with a different one (lets forget the fact that you'd probably just do this with two properties). You have a sub-page storing the smaller image in a property at http://myepisite/News/SomeArticle/LowImagery, which is hidden from the site. The way that you trigger the load of the low image is by URL QueryString, e.g. http://myepisite/News/SomeArticle?bandwidth=lo. (If you want some more tips on achieving this URL neatly, see my posts or other posts on URL rewriting.) Anyway, you could write a custom property type etc. to do this, but that's a fair whack of work and you'll need to create a new custom property for every content type that you might want to replace.

So how do I achieve this in a neat, generic way? EPiServer provides a nice way, but it's not the most well documented route and neither do they really recommend it. Still, I think it can work well if properly implemented. The way I implemented to achieve this was using a custom Property Get Handler.

When EPiServer asks for a page, it builds a PropertyDataCollection of all the properties on that page, along with their values. This PropertyDataCollection contains all the user-defined properties along with some that EPiServer add in as well such as PageLink, PageLanguageBranch and others. These are absolute lifesavers, although they are not well documented. The PropertyDataCollection has a default indexer which, when called, calls to a helper method to get the actual PropertyData for a property. The default helper method is a static method called 'DefaultPropertyHandler' on EPiServer.Core.PropertyGetHandler. This helper method looks for the the actual property data in four stages:

  1. It looks at the property on the current page and the current language
  2. If that is empty, it checks to see whether the property is language specific and, if it is, whether the current language is the master language. If not, then it grabs the master language page and returns the value from that property.
  3. If language isn't an issue, then it tries to get the property value from the linked page, if any.
  4. If there is not data on a linked page, then it tries to return a dynamic property value with that property name.

This works well and is the default that probably fits 99% of EPiServer installations. However, EPiServer kindly allow us to replace this default Property Get Handler. All you need to do is write your own method that matches the delegate for the handler, and then set an EPiServer property like so:

EPiServer.Core.PropertyDataCollection.GetHandler = new GetPropertyDelegate(Test.BandwidthPropertyGetHandler.BandwidthPropertyHandler);

I'm sure you can set this in most places where you need it, but I just put it into the Application_Start of Global.asax.cs. So we can see how easy it is to override the property handling, but what does our custom method actually look like? The following code is incomplete, untested and partially commented out, but it should give the idea. The two parameters coming in are the property name being queried for data and the property data collection for the current page/language. Notice that rather than use the default indexer for properties, when asking for a property data value I am explicitly calling the 'Get' method - this prevents nasty infinite loops where my custom handler keeps calling itself.

namespace Test
{
    public static class BandwidthPropertyGetHandler
    {
        // Methods
        public static PropertyData BandwidthPropertyHandler(string name, 
PropertyDataCollection properties) { // check querystring to see if we need to replace property (where possible) HttpRequest Request = System.Web.HttpContext.Current.Request; if (Request.QueryString["bandwidth"] == "lo") { // we need to swap low bandwidth if it's the right property name // you could drive this any way you like - don't hardcode it in production :) if (name == "ArticleImage") { // lets reach out and grab the data from the sub-page PageReference ThisPageReference = (PageReference)properties.
Get("PageLink").Value; PageDataCollection ChildPages = EPiServer.DataFactory.Instance.
GetChildren(ThisPageReference, LanguageSelector.MasterLanguage()); foreach (PageData ChildPage in ChildPages) { // find an article subpage if (ChildPage.PageTypeName.ToLower() == "article subpage") { // grab our property and return it return ChildPage.Property.Get("ArticleImageLow"); } } } } // just return the default handler return PropertyGetHandler.DefaultPropertyHandler(name, properties); } } }

In my actual implementation I handle languages properly, error handling, null property values and all sorts of other things, but it should be fairly obvious how that would work. In essence, this is a very simple way of customising properties to make them do fairly clever things without customising property types themselves. In fact, this would be a nice way to retro-fit a feature such as bandwidth tailoring or other targeted content to an existing type. Just remember that if it's not a special case you should be handling, call the default handler to do it's stuff with that property! Also, it might be best to try to keep your injected property types the same as the property type on the owner page. Not sure what would happen if you messed with that.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Tuesday, December 09 2008 at 12:42 PM by Dan Matthews

I needed to throw together a quick geolocalisation demo for EPiServer v5 R2 the other day and to do that it was necessary to override some of the default URL rewriting behaviour of EPiServer. I knew it could be done, but I'd never actually had to write a custom URL provider before, so Ted Nyberg's blog post on rewriting in EPiServer gave me a good kick-start.

My geolocalisation changes worked a treat (maybe I'll blog about that another time) but I did come across one really nasty 'feature' in EPiServer. I did find a workaround though, so I'll share it with you. Some background first though.

As you may know, EPiServer has the nice ability to add a file extension on to pages. Before you rush off and try this out on your live site, be aware that it does change the default behaviour a little, for example it stops trailing slashes from working on the URL, e.g. this works:

http://myepisite/SomePage/

...but this does not...

http://myepisite/SomePage.htm/

In fact, I like this feature because when using an external cache provider (such as Akamai), page extensions are A Good Thing as it knows how to treat them, and it also reduces the number of a URL 'possibilities' for a single page, so reducing the cache usage. As a bonus, it can also help with security as it slightly abstracts the page engine from the URL. Why not use the extension 'cfm' and then watch and laugh as all the ColdFusion-specific attacks roll in :)

So I set an extension on my geolocalisation demo of '.htm' (done in the urlRewriteExtension property of the site settings element in Web.Config, make sure you put the dot in the extension as well otherwise you'll get SomePagehtm). So far, so good, and the out-the-box demo templates site appeared to run fine. But then I noticed a weird quirk. On the menu across the top, the various links made sense, for the most part:

News -> http://myepisite/en/News.htm

Events -> http://myepisite/en/Events.htm

and so on... but the Start link was all messed up:

Start -> http://myepisite/en.htm

What was strangest of all though was that this link actually worked! This made no sense on any level, and it was obvious that some internal fudge in the default URL rewriter was catching this as a special case. This was confirmed when I found this post from EPiServer support. They'd obviously found this 404'ing so built a special case for it.

So why do I care? Because this breaks the URL model and breaks my geolocalisation scheme quite badly. That link should 404 or else I have an issue. Ideally, I want to actually write out the proper link. So I started digging. It turns out that you get a link like this when you have an EPiServer Start Page and ask for the LinkURL for it. The default URL rewriter seems to munge it up and spit out this crazy short URL rather than a nicely formatted link. This is the same for any language, for example the Swedish start page gives sv.htm. Ideally though, I would want it to write out something like this (the page is actually called Public in the English version):

http://myepisite/en/Public.htm

I mean OK, it looks like any other page rather than a start page but surely that's better than en.htm! So... how do we go about getting the right page link rendered out and bypassing EPiServer's little 'fix'? Well, we can do it with the URL rewriter. I'll let Ted's post explain how to actually create the URL rewrite provider, but once you have the rewrite provider ready, you can override the ConvertToExternalInternal method as follows:

protected override bool ConvertToExternalInternal(UrlBuilder url, object internalObject, Encoding toEncoding)
{
    // apply default rewriting first
    bool bRewriteSuccess = base.ConvertToExternalInternal(url, internalObject, toEncoding);

    if (bRewriteSuccess)
    {
        string[] urlSplit = url.Path.Split('/');
        
        if (urlSplit.Length == 2)
        {
            // default page

            string DestinationCountryCode = urlSplit[1].Substring(0, 2);

            EPiServer.Core.PageData StartPage;

            try
            {
                StartPage = EPiServer.DataFactory.Instance.GetPage(
new EPiServer.Core.PageReference(EPiServer.Configuration.Settings.Instance.PageStartId),
new LanguageSelector(DestinationCountryCode)); } catch { // no page with that language, just grab the link anyway and it will
still work just with the current language name
StartPage = EPiServer.DataFactory.Instance.GetPage(
new EPiServer.Core.PageReference(EPiServer.Configuration.Settings.Instance.PageStartId)); } url.Path = "/" + DestinationCountryCode + "/" + StartPage.URLSegment +
EPiServer.Configuration.Settings.Instance.UrlRewriteExtension; } } return bRewriteSuccess; }
This is not a fully-tested solution and it might need more work, but it shows that it is possible to fix this troublesome default behaviour. My geolocalisation demo then wrote out links as I would expect, and seemed to work perfectly across languages too. Hope this is of some use to anyone with similar issues even if it only gets you started on a fix!

Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Friday, December 05 2008 at 11:53 AM by Dan Matthews
A friend working at Graphico of my recently sent me some SQL that purposed to look for missing indexes in you databases.  It pretty much sat in my inbox for a while until I had time to look at it (which I have just done).

It was a great little script and proved very useful in identifying performance improving indexes that we could include in the database that we're developing.  I asked my friend where the SQL was from and he pointed me to the article in question on the MSDN site, which you can find here:

http://msdn.microsoft.com/en-us/magazine/cc135978.aspx

It really is worth a read and has some very interesting stuff in it.  Cheers for that, Paul - most useful!

Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Tuesday, December 02 2008 at 09:53 AM by Matt Nield

I've found a bug with IE8 Beta 2 (in both IE7 and IE8 browser modes) where list boxes that, although disabled but containing selected items, do not show the selected items. Here is an example of what should be displayed

For those of you who are not using IE8 Beta 2, here is what it appears like:

I have logged the bug on their forums at http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx?dg=microsoft.public.internetexplorer.beta&tid=55a9ace5-380d-408c-aa54-2d997de1f245&cat=〈&cr=&sloc=&p=1 so read and vote if you've found this to be a problem too!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Thursday, November 27 2008 at 12:01 PM by Dominic

I've just managed to get the .NET 3.5 style of WCF Web Programming Model services to work inside an EPiServer 5 R2 site on IIS 7 and Windows 2008.  I had a few difficulties finding out how to integrate the new model into IIS/ASP.NET and then further problems getting it working in EPiServer.  Here, I outline the solution.

Context

I'm currently designing a site that will be using the Akamai Edge Suite of technologies (www.akamai.com) and so I desire that all client access is through the caching layer.  Additionally, I'm motivated towards a REST model for web services to support a greater degree of caching.

The new WCF Web Programming Model is ideal for this purpose as I can wrap service parameters directly into the URL and reduce the coding effort considerably.  I had been concerned about the integration of services into the same website as EPiServer because of how the URL mapping works in the Web Programming Model.

Solution

The solution is really easy once you realise that the typical EPiServer installation changes the default ASP.NET configuration.  Specifically, you may need the following:

  • Create a new folder to host your services
  • Create a small web.config in this folder (or use location tags in the main web.config file) and add service handlers
  • Create a ".svc" file for the service
  • Create the supporting .NET service code

Create a new folder to host your services

This is necessary to allow a separate application configuration.  You can change the main application configuration at your own risk, however :)

For the purposes of this post, I'll use "~/services/".

Create a small web.config for this folder and add service handlers

You'll need to add the following:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="svc-ISAPI" path="*.svc" verb="*" modules="IsapiModule" 
           scriptProcessor="%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
           resourceType="Unspecified" 
           preCondition="classicMode,runtimeVersionv2.0,bitness32" />
      <add name="ServiceHost" path="*.svc" verb="*"
           type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel,
                 Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
           resourceType="Unspecified" preCondition="integratedMode" />
    </handlers>
  </system.webServer>
</configuration>

Now I took this from a cleanly created website with no configuration (using the IIS management console) and I recommend that you do the same.

Create a ".svc" file for the service

This file is created in the service folder and forms part of the URL so name it accordingly.  I'll just use "service.svc" for illustration:

<%@ ServiceHost Language="C#" Service="Service" CodeBehind="~/App_Code/service.cs"
    Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

You should name your services more appropriately, of course.

Create the supporting .NET service code

So, you need to create the classes.  Here, I'm using a simple file in the App_Code folder, but you might prefer to use a separate code project and assembly.  Here's a simple example:

using System.ServiceModel;
using System.ServiceModel.Web;

[ServiceContract]
public interface IService
{
  [OperationContract]
  [WebGet(UriTemplate = "test?s={s}")]
  string test(string s);
}

public class Service : IService
{
  public string test(string s)
  {
    return "test: " + s;
  }
}

So, this is a very basic service with a single HTTP GET method that returns some data dependent on a single query string parameter.  A perfect REST example as the result is defined by the input, there is no change of state (so two identical GET requests result in the same value) and so the response is suitable for caching.

Using the service

So now, you can access the service as http://your_episerver_site/services/service.svc/test?s=YourTestString.  ASP.NET integration (and IIS) requires the use of a service extension, in this case ".svc", however this article may help you to remove this issue: http://blogs.msdn.com/bags/archive/2008/08/22/rest-in-wcf-part-ix-controlling-the-uri.aspx but don't forget that EPiServer already does some URL rewriting and so you'll have to make sure they don't conflict!

Metadata


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Thursday, November 20 2008 at 05:10 PM by Stephen Horsfield

One of IE8's new features is a that when closing a window or tab, it can remember the session ID and therefore maintain the session with a website. This is an advantage if you accidentally close a window or tab, but there is a problem.

For example, if you have several logins for a site, each login giving totally separate functionality of the site (e.g customer and administrator), then you may close your browser and login as someone else. What you may find is that when you open a new window, you are already logged in as the other person. Why does this happen?

IE8 seems to use the first window a storage mechanism for sites visited in this browsing session. When visiting a site, the unique Session ID is generated and then stored in this host process. When opening new tabs and windows the new process checks the host process to see if the website has been visited and if so returns the existing session ID.

So to re-iterate, if you have at least 1 browser window open, all subsequent tabs and windows pointing to a specific site will all generate the same session ID.

In order to get around this "problem", you should close all instances of IE8. The session information seems to be stored in memory rather than on disk, so by closing all of these instances, the problem goes away.

This serves as a warning to both developers and kiosk/Internet café users. Developers should provide the ability to log out of a site so that the Session is cleaned up after a user logs out. Kiosk/Internet Café users should close ALL Internet browser sessions down before leaving!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Thursday, November 20 2008 at 09:15 AM by Dominic

The 3 types of connections Silverlight can make are:

  • Connections to web services and WCF services
  • HTTP requests (via HttpWebRequest and WebClient)
  • Raw data transfers

When building one of your early applications, you may choose to try out one of these classes to get back a really simple piece of HTML, purely to test the connection. For example:

protected void Button_Click(object sender, EventArgs e)
{
    WebClient wc = new WebClient("http://www.google.com");    
    wc.DownloadStringAsyncCompleted += new EventHandler<DownloadStringEventArgs>(wc_DownloadStringCompleted);    
    wc.DownloadStringAsync();
}

protected void wc_DownloadStringCompleted(object sender, DownloadStringEventArgs e)
{
    if(e.Error == null && e.Cancelled == false)  
    {        
        Debug.WriteLine("Data downloaded = " + e.Result);    
    }
}

(N.B I apologise if this doesn't compile, I've just typed this by hand.)

If you run this, you'll find it generates a SecurityException, but why?

To improve security, the only connections you can make without any security implications is your own website. If you want to call another website, Silverlight needs to check a few things. Firstly, it looks for a policy file called "clientaccesspolicy.xml", which is a file used by Adobe Flash to find out if it allows connections from Flash applications. If this file is missing, it then looks for "crossdomain.xml", which is a Silverlight version of this file.

  • If one of these exists AND the policy file allows connections, then the application will be allowed to connect.
  • If neither exists, or the policy in an existing file denies access to the requested virtual directory, then a SecurityException will be thrown by the application.

To overcome this problem, you have 2 options

  1. Check the website has an API to use the capabilities you are after. Google and Digg have service APIs in order to allow applications to do this.
  2. Write a web service (or WCF service), that does the enquiry for you.

If you need to see the contents of these files, I have found Fiddler an excellent tool for this purpose.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Monday, November 17 2008 at 12:48 PM by Dominic

EPiServer Norway are associated with an EPiServer community project called EPiCode which had its annual awards on the 12th of November as part of the Christmas Tech Forum. I was really pleased to see the Module of the Year award went to my pals over at NetworkedPlanet for their EasySearch module. Unlike some of the other modules on EPiCode, it isn't free to use commercially - but it is free to download and try out and fills a nice gap in the EPiServer search space.

A bunch of other 'active contributors' were lucky enough to get an iPod Shuffle in the awards - including me for contributing CloudCuckoo and HyperThumbnail on behalf of Interakting. Thank you EPiServer Norway!

You can read more here.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Monday, November 17 2008 at 12:35 PM by Dan Matthews

I put my VPC's on my external hard disk and run them off there, as the hard drive can run independently of Windows.

I've noticed over the past few months, that randomly, my external USB 2.0 hard drive (Freecom 400GB) disconnects for no reason and I get a balloon in the system tray with the title "Delayed Write Problem" , then something to do with G:\$MFT or G:\$Bitmap.

Yesterday, I was defragmenting my external hard disk and noticed it kept happening. I turned it off and on again, started defragmenting and the same problem happened.

I thought it might be the writing caching, which helps improve performance, so when viewing the properties of the drive (My Computer -> [External Hard Disk] -> Right-click Properties -> Hardware -> Properties -> "Enable write caching on the disk"), I turned this option off.

Another defragmentation session and the same problem happened again and again.

What I finally realised was that I was using some software (DAEMON Tools Lite) for mounting ISO's to a CD drive. Although the software wasn't running, I still had the CD drive present in my drive listing. I loaded up DAEMON Tools Lite and turned off the emulated CD drive (which I wasn't using anyway) and HEY PRESTO! it was working.

I defragmented half the drive and then turned write caching back on and it was fine!

Hope this helps someone, as when a hard drive disconnects and a VPC is running off it, you are in trouble!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Wednesday, November 12 2008 at 09:23 AM by Dominic

Introduction

Interakting use both Open Source and proprietary products to deliver solutions for many companies. We always try to select the best tool for the job, and when it comes to Content Management it is no different. We have a range of tools we consider using including various Open Source tools (e.g. Nuxeo, DotNetNuke) and also our proprietary offerings (EPiServer, ADXSTUDIO). In the context of many projects it would certainly be possible to deliver a ‘successful’ project in either a proprietary or an Open Source solution. However, when we consider budgetary, functionality, deadline, support and longevity constraints, all of these areas are problematic in the Open Source arena, whereas proprietary systems such as EPiServer can provide an arguably better and more cost-effective solution. This article discusses some of the reasons for this. The majority of 'pure CMS' sites we deliver are on the EPiServer platform and so this will form the basis of our discussion. Interakting is an EPiServer Solution Partner.

Budgetary

With a proprietary CMS such as EPiServer, the main costs are ‘up front’. The client would be buying a licence to use EPiServer CMS, and the cost of this covers the effort and time taken by the vendor to develop and support the product. This means that the vendor does not need to find other ways to recoup their costs beyond the licence fee and an optional small annual support fee. The client can therefore budget for the outright licence as a clearly transparent and defined cost.

Open Source costs are far less clear, as companies who ‘own’ an Open Source initiative may give the software away ‘free’ but then seek to recoup their costs, even if only running costs. This is usually done by support contracts, consulting or selling additional ‘modules’. It is easy to be trapped into a ‘free’ product and then find that the actual cost is far higher.

Functionality

As proprietary systems are designed to be sold as widely as possible to reach the maximum number of customers, functionality in proprietary systems is usually excellent and if additional functionality would assist their sales then the company owning the product will often update their core product or provide value-add modules at low or no cost. This is very much the case with EPiServer, who have grown rapidly due to their responsiveness to customer demands and now have many thousands of seats worldwide. The CMS is particularly user-friendly and intutitive and can be used by novice users without the need for costly training.

In the Open Source arena this becomes more complex. The popular view is that the community ‘works together’ to build a product for the good of the community. This works well, to a point, but ultimately people are not entirely altruistic. Sooner or later (and sometimes always) they only contribute to things that benefit themselves. This means that the ‘out of the box’ product is often minimal functionality, and even if it is fairly well featured then those features are often not very flexible and designed for the use of the company that commissioned them with specific needs. It is unlikely the community will help add or update functionality and therefore it is left to the project team to do so, which can be fairly hard and time consuming. User training is likely to be required, particularly post deplyoment when users change jobs and new users need to work with the CMS.

Deadline

As a general rule, any proprietary systems must be designed to provide a very rapid solution as this is a key selling point since the market is very competitive and unforgiving. In this regard EPiServer stands up very well which is one of the many reasons that Interakting has selected this tool. The well-featured out of the box nature of EPiServer, together with the well-documented and supported APIs, mean that a robust solution can be built rapidly and efficiently. The tools are built with the clients business needs clearly in mind as much as the developers.

In an Open Source project, it has generally built by developers with a very code-centric approach. There is an expectation that the basic product will be customised by developers as needed, and the out-of-the-box functionality capability is usually minimal. Even with ‘starter’ kits for a particular tool, there is often a large amount of code and customisation to be done. Agencies promoting open source solutions capitalise on this aspect as it is very lucrative to develop the added functionality needed for more complex reqirements such as multi-lingual non-Latin support

Support

With EPiserver, as part of the licence agreement, the vendor undertakes to provide support and their reputation relies on this support being accessible and effective. The support is also usually rapid and efficient to respond with managed Help Desks staffed by knowledgeble individuals. They are able to respond with authority on support issues as they designed, wrote, maintain and own the codebase.

For an Open Source tool, the support is either an expensive add-on from the company providing the tool or is community based. If a company is supporting a tool this is often not so much of a problem, although there is an issue that they are supporting code that they quite possibly did not write. From our experience (remember that we also work with Open Source solutions when we feel it appropriate), support from the community is often slow and inadequate for projects that have a critical path.

Longevity

EPiServer is committed to the products they sell and even if they discontinue a product will generally provide migration or upgrade paths. Generally speaking, it will also be clear in advance whether a product will be passing out of support and therefore a proper exit or migration strategy can be planned well in advance. EPiServer is also helpful in that, in the event of it ceasing to trade, it has made its code available to its licensees through an escrow arrangement at a nominal annual cost (although this is optional).

Open Source projects are often left unfinished or unsupported once the community using them has moved onto something different. As a general rule, Open Source projects have a limited time in which they are actively updated and maintained and once a critical inactivity threshold is reached then they effectively become ‘legacy’, are taken into closed source or amalgamated into something larger. It can also be harder to plan an exit strategy as the ‘lifetime’ of a product is usually unclear.

Summary

In summary, we believe that for the many projects, the unknowns and variables involved in taking the Open Source route will result in a slightly higher initial cost of development and deployment and a significantly higher cost of ownership over a two year period following the initial go-live.

By choosing to use a well-proven CMS which uses the .NET framework, a project is grounded on a solid, well defined and tightly costed product and the real cost of deployment and support over a 2-5 year lifetime can be estimated with a far higher degree of accuracy. Ongoing maintenance, functional enhancements and support will also be easier to define and budget. Finally, a large pool of .NET developers able to work with EPiServer and are readily available at competitive day rates meaning the client has total flexibility and would not be locked into any single supplier in the future.

If you're looking for a CMS solution for your web site, shouldn't we be talking?


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Tuesday, November 11 2008 at 10:58 AM by Dan Matthews

Last night I was at a BCS Young Professionals Group meeting at the BCS offices in Southampton Street, London. The meeting was part of a 'SkillCentre' series being run with the help of a consultant called Anthony Rees facilitating, and the subject last night was 'Negotiation Skills'.

The session itself was excellent, culminating in groups coming up with a simple mnemonic to remember some basic concepts for negotiating. The group I was in came up with the mnemonic 'winwin':

What do you want

Investigate feasibility

Note it down

Walk in their shoes

Identify tactics

Negotiate!

Another group came up with the 'winning' mnemonic of 'KPMG', which raised a chuckle. I'm not sure I can remember it exactly, but it went something like:

Know

Prepare

Maximum (& minimum)

Goals

Personally, I found it memorable but less useful. But that's probably just me being biased. Following the main session there was a chance to network over wine and nibbles which was just as valuable as the session itself. And kudos to the BCS for putting on a nice Chilean Merlot :)


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Thursday, October 16 2008 at 10:36 AM by Dan Matthews

After various conversations on both internal and external projects, I’ve noticed that some of our web projects were being developed using a Session state called InProc.

InProc means In-Process, so IIS is hosting all of the

Session[“Dom”] = “Idiot!”; 

variables. Now, if the web application eats up too much memory, IIS 6 and above can be configured to recycle the Application pool – a contained unit of web sites, in order to free up memory. This is good for IIS but baaaad news for your website, as everything in the Session is lost – that could be shopping basket, current order status, user details! InProc is a bit of a quick and nasty method of developing as it just does its job, assuming that you are not going to host this to a larger audience (over about 5 users).

As I found out with any large project, nothing goes to plan, so, the best thing to do is to use StateServer and not InProc – but WHY?

StateServer is a totally out-of-process service that runs on either the same web server or a different server entirely. Session data is saved to this service so if the AppPool recycles, you have no problems whatsoever. Also, the data needs to serialize properly in order for it to be saved to the service.

Whats the point I hear you ask? Well, the point is that if you use InProc and your application gets load balanced (often without your knowledge), the website won’t work properly. Remember, load balancing is decided, by either the hardware or the software, to help manage the network traffic to a destination server. So 1 request to go to Server1 and another or Server2, or even ServerX! Youch! So your site’s Session could be stored on another machine.

StateServer works because all of the web.config’s point to the same machine, so they all work off that one service.

The other option is SQLServer, which stores it in SQL Server, which is more for web farms (multiple physical PCs), rather than web gardens (multiple virtualized PCs). Or you can use Custom for a custom implementation (e.g ODBC or XML), or Off to turn it off completely.

Therefore, a good recommendation is to always change your web.config to say:

<sessionState mode=”StateServer” … />

And start the ASP.NET State Service on your machine. This way to can always revert to InProc if you need to, but you are still ready for the switch over.

Believe me, it’s a lot easier to start out this way, rather than have to work backwards.

It is always a worthwhile exercise!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist
posted @ Thursday, October 09 2008 at 03:35 PM by Dominic

When working on a project recently, the data saved back to the database was huge. We are talking well over 100 properties. After talking to my Java buddy, he said that one way is to create an IsDirty method that returns if the object has changed state.

The IsDirty() method is used to query the state of an object - if it has been modified or not. The implementation is up to the developer, but ultimately it's use can save you a trip to the data source.

I have split this example into 3 stages:

  1. First attempt
  2. Refactored
  3. Event Handled

N.B. This article helps someone in (archaic) .NET 2.0 - but if you've looking to develop for .NET 3.5, it might be worth looking into DependencyProperty's, which caters for this sort of problem.

First Attempt

The problem I found when prototyping this is that it can be quite impractical at first glance:

class Customer
{
    private string firstName, surname;
    public Customer(string firstName, string surname)
    {
        this.firstName = firstName;
        this.surname = surname;
    }

    public string FirstName
    {
        get { return firstName; }
        set 
        { 
            if( firstName != value )
            {
                IsDirty = true;
                firstName = value;
            }
        }
    }
    public string Surname
    {
        get { return surname; }
        set 
        { 
            if( surname != value )
            {
                IsDirty = true;
                surname = value;
            }
        }
    }

    public bool IsDirty { get; private set; }
}

 

This is a bit bloated. Also, it relies on every property having to check for itself whether it is equal or not, setting the IsDirty property and also assigning the value.

After writing this and implementing a few more properties I found this to be a bit too impractical. Instead, I realised that they are all basically doing 3 steps:

  1. Checking the previous value to the new value.
  2. Setting IsDirty.
  3. Assigning the new value.

This example needs simplifying - or refactoring to be more precise.

Refactoring

Instead, I decided to implement this behaviour in a method called SetValue<T>() , which would raise events when a property has changed. This allows the IsDirty property to be changed centrally and debugging to be centralized.

Firsty I created the method:

private void SetValue<T>(ref T varName, T value)
{
    if (varName.Equals(value))
        return;
    
    IsDirty = true;
    varName = value;
}

 

Now, we can change our properties to:

public string FirstName
{
    get {return firstName; }
    set
    {
        SetValue<string>(ref firstName,value);
    }
}

public string Surname
{
    get {return surname; }
    set
    {
        SetValue<string>(ref surname,value);
    }
}

This is one implementation of it, but I decided to extend it to event handling as well, so that even the outside world can be notified about what is changing.

Event Handling

I decided to also implement this is in a typical Microsoft fashion: OnPropertyChanging and OnPropertyChanged.

In order to turn this into an event driven model I need to do a few things:

  1. Create some event arguments describing what is being changed.
  2. Add some event handlers to trigger a notification that they have been changed.
  3. Trigger the events from within your code
  4. (Optionally) wire up the events.
  5. Trigger the events from within your code

Create event arguments

Since I am using events, I want to create event arguments detailing what has changed. I have implemented this in 2 identical classes (and 1 base class). Here I have implemented a base class, and 2 classes which improve the clarity of the base class. I have chosen clarity over code bloat:

//Base class implementation