Wednesday, 12 March 2008

Dummy Content Generator for EPiServer

It's a part of developer's job is to write a code ... it's obvious ... but after that we are also suppose to test the code and make sure that new features actually work. And that's where a test environment including test data is very useful. Creating a few EPiServer pages doesn't take much time so usually it can be done manually... but what if you need 1k or 10k pages? I guess that's a point where you would prefer to generate those pages.

I was facing a problem like that some time ago ... and I decided to wrote Dummy Content Generator!

I know ... it doesn't look very impressive ... but still it is very useful. This small tool made my life simpler :)


How to use Dummy Content Generator
  1. First of all - crate page types which you want to use
  2. Create XML where you define how your dummy data should looks like
  3. Define where dummy data should be added (you can specify parent page ID)
  4. Run it!
Most of the steps is quite simple and self-explanatory, the only one which is worth explaining is creating the XML. Check an example:



As you can see in this example, tag pages contains one page tag which has following attributes:
  • count - defines number of pages which will be generated based on this tag, 1 page in this case,
  • type - page type which will be used,
  • name - name of the page.
and elements:
  • properties - this is a list of properties which you want to set, in this case I don't want to set any properties, this is just an grouping node,
  • children - list of the pages which will be generated under the page.
Now, within children tag there is another page tag, it's worth noticing that this time count attribute is set to 5 which means that 5 pages (article - 0, article -1, article - 2 .... ) will be generated.

And properties ... here we have in general two options:
  1. <property name="Title" randomvalue="true"/>
    It will create property with random value! How? Dummy Content Generator will detect property type and then it will open text file named in the same way as property type to get list of possible values.

    For instance for property of type String it will open file EPiServer.Core.PropertyString.txt, for property of type URL to image it will use EPiServer.SpecializedProperties.PropertyImageUrl.txt and so on ...

    This approach facilitates extending the Generator by custom properties. It's also very simple to change my dummy strings with your own one, maybe more meaningful.

  2. <property name="WriterName" value="Marek Blotny"/>
    Above line will create property with specified value. It will not use random values! No magic here.
And this is final result, six new pages:




How to install Dummy Content Generator on EPiServer 5:

  1. Download zip file
  2. In EPiServer CMS Manager, select the existing EPiServer Web site and then
    Action -> Install Module.
  3. Select DummyContentGenerator.zip to install and that should be all!

Remarks
  • To simplify creating the XML you can download schema from here.
  • VS 2005 project with all sources can be downloaded from here.
  • Sample XML
  • This tool is on a very early stage, it was working for me well, but of course I didn't check all possibilities. It would be great to get some feedback from you, in particular please let me know if you find any bugs!
  • If there will be an interest to improve or add new features to the Generator I'm willing to publish source code on EPiCode and help with improvements.

Tuesday, 4 March 2008

NotSupportedException: The property Title is read-only

Few lines of code which are quite self-explanatory and used to be working in pre-EPiServer 5 era.

// get page instance
PageData page = DataFactory.Instance.GetPage(new PageReference(id));

// set new value
page.Property[
"Title"].Value = "here comes some new value!!!";

// save and publish
DataFactory.Instance.Save(page, SaveAction.Publish);


Looks nice and easy ... but there is one problem ... it throws an System.NotSupportedException saying that "The property Title is read-only."

You can use DataFactory.Instance.GetPage() method to load pages but EPiServer 5 will return read-only instance of the page. Compiler will not complain that you are assigning new value to the read-only property but in a runtime you will get the exception. If your goal is to update a page you should use this method to get modifiable instance: PageData.CreateWritableClone()

and it whole should looks like that:

// get read-only page instance
PageData readonlyPage = DataFactory.Instance.GetPage(new PageReference(id));

// get modifiable instance

PageData modifiablePage = readonlyPage.CreateWritableClone();

// set new value
modifiablePage.Property[
"Title"].Value = "here comes some new value!!!";

// save and publish
DataFactory.Instance.Save(modifiablePage, SaveAction.Publish);



Why EPiServer 5 forces us to write this one extra line of code? Answer is performance! Returning read-only instances is significantly faster and moreover ... in most cases that is what you really need. I guess that in 90% of cases you are accessing data simply to display it for the users. In the rest, 10% cases, you want to update those data. It makes perfect sense to have it working faster in typical cases and to write one additional line of code when you want to modify properties.

Saturday, 1 March 2008

EPiServer 5 vs. EPiServer 4.61 part I - GetPage()

We have been using EPiServer 4.61 intensely for over a year now, during this time we have managed to deliver a few successful projects on this platform. It took us some time to learn how to use EPiServer effectively. Release of EPiServer 5 was welcomed by us very enthusiastically. All the new features and improvements were very promising. But before porting our EPiServer 4.61 applications to newer version we wanted to check what can we expect from EPiServer 5.

With version 4.61 we were facing many performance issues and we were forced to cache lots of data on our own to meet performance requirements. (you can read more in Adam's article)Therefore we have decided to check how fast/slow EPiServer 5 is. Good place to start is a method which is absolutely essential for all developers – Global.EPDataFactory.GetPage(). This method retrieves a PageData object with information about a page from either database or cache. It’s quite hard to use EPiServer and don’t use this method ;)

Preparation

First of all I generated 22k dummy pages. Structure of generated pages and used page types was the same as we use on production servers. All page IDs were stored in an external text file. In each run, test was loading arbitrary pages, it was using only IDs from the text file. Having all IDs in an external file, it was possible to load pages right after starting server. This way I got the times which are required to load pages from a database.

Test scenarios

  1. In first scenario IIS server was just restarted which means that cache was clear and all requests were forcing EPiServer to retrieve pages from a database.
  2. Second scenario was an opposite to the first one – all pages were loaded earlier, which effectively means that all data was cached.

Additionally I was checking how dynamic properties influence overall performance. All tests for both scenarios were done first without dynamic properties and secondly with 25 dynamic properties set.

Results

First Scenario:



Results show that loading pages from a database is much faster in EPiServer 5. It took EPiServer 4.61 significantly more time then EPiServer 5 to return 15k pages! Version 4.61 needed 140 seconds whereas version 5 only took 20 seconds.

An interesting fact is that dynamic properties in this case didn’t change times almost at all on both versions. Which is understandable barring that the page has to be read from the database anyway.

Second scenario:



Again EPiServer 5 beats EPiServer 4.61 severely. EPiServer 4.61 cache uses “copy-on-read” approach, in version 5 cache data are read-only. It means that by default we are getting read-only objects from cache. Developers need to call different method to get modifiable copy of the object (EPiServer.Core.PageData.CreateWritableClone) but honestly, as a developer, I can live with that, it’s much more important for me that the cache works much faster for the regular viewers!

There is another interesting conclusion … if your pages are loading slow in EPiServer 4.61 try to get rid of dynamic properties … you can get quite nice speed up thanks to that!

Well, there is no need to write much … GetPage() is hell of a lot faster in EPiServer 5. In the next part I will check if GetChildren() behaves in a similar way.