EPiServer’s ObjectStore

We’ve been looking at the way to efficiently store a lis of quotes some time ago. And Steve suggested that if we’re to store a gian number of quotes, we may look into some misterious being called ObjectStore…

If there will be many qoutes, e.g. you buy a “100.000 quotes of the day” database, you might want to put them into a separate table in the database. Seasoned EPiServer developers tend to think that everything can be stored as pages in EPiServer, which is kind of true, but not necessarily wise.

Another option could be to store the quotes in the ObjectStore, the general EPiServer storage feature, which can hold about anything you’d like, efficiently, quickly restorable, searchable, indexable, highly available and environmentally safe. It might even solve the global warming problem while we’re at it. Ok, maybe not. Truthfully, only a few developers outside of EPiServer know how to use it, and quite alot of us inside have no clue whatsoever. But, the tales I’ve heard about it would nominate it as a prime candidate for a quote system like this. Right now, it is storing things like XForms definitions and data, WSRP stuff, Content Mirroring data and lots more. It’s been around since 4.50 (I think) and is said to be documented – eventually, until then I guess we’ll have to resort to other ways of doing things.

MmmMmm… tasty!

Research mode “ON”.

There is no documentation, allright, but there is Reflector. Between the reflector and the sample server, there can be no secrets that can hide form us :)

Basically the ObjectStore is a way of persisting any serializable object (with some minor adjustments).

  • Object store is divided into Schemas.
  • A schema seems to be way of grouping types of objects into easily manageabble pools
  • A class type has to be contained within a schema to be persisted.
  • A type needs to be registered within a schema before you can write to it.
  • A type needs to implement EPiServer.BaseLibrary.IItem interface and be marked as Serializable for the ObjectStore to be able to serve it.

The Research Field

The namespaces of your interest is EPiServer.BaseLibrary, namely the following parts of it:

namespace EPiServer.BaseLibrary
{
public sealed class Context
public interface IContext
public interface IItem
public interface IItemList : IEnumerable
public interface IObjectStore
public interface IRepository
public interface ISession
}

Then you may want to open EPiServer.XForms.XFormData and EPiServer.XForms.XForm especially the Save() method of the latter is very educating.

The code for the ObjectStore implementation lives in the EPiServer.Implementation namespace but having all the interfaces exposed its implementation details should not be of our concern. Suffice to say itseems to be flexible ane extensible. You can have it sitting on an Oracle & Microsoft SQL Server databases as well as having it stored In an XML file. I assume there would not be much trouble replacing the object store looking as the Logging service has it setup dynamically through settings in its config file.

The results

  • The class you want to persist should inherit IItem and be serializable.
  • The default repository is stored in the Context and is capable of creating more sessions for us
  • Bah, enough of the bulleted lists… let the code speak for itself…

using System;

using System.Collections.Generic;

using System.Text;

using EPiServer.Implementation;

using EPiServer.Implementation.Serialization;

using EPiServer.BaseLibrary;

using System.Xml.Serialization;

 

namespace Cognifide.EPiServerTest.ObjectStore

{

    [Serializable, XmlInclude(typeof(CogObjectStoreItem))]

    public class CogObjectStoreItem : IItem

    {

 

        string data;

        private object id;

        private string name;

 

        public object Id

        {

            get { return this.id; }

            set { this.id = value; }

        }

        public string Name

        {

            get { return this.name; }

            set { this.name = value; }

        }

 

        public CogObjectStoreItem(object id, string name, string data)

        {

            this.data = data;

            this.id = id;

            this.name = name;

        }

 

        public void Save()

        {

            ISession session = null;

            try

            {

                // check if there is a schema for the type, if not create it.

                if (Context.Repository.SchemaForType(this.GetType()) == null)

                {

                    TypeSchemaBuilder.RegisterSchemaAndType

                        (“CogObjectStoreItem”, this.GetType());

                }

 

                // get a new session from the current context.

                session = Context.Repository.CreateSession();

 

                // wrap it in a transaction

                session.BeginTransaction();

 

                // make sure the id has been defined.

                if (this.Id.Equals(Guid.Empty))

                {

                    this.Id = Guid.NewGuid();

                }

 

                //persist

                session.Save(this);

                session.CommitTransaction();

            }

            catch (ElektroPostException exception)

            {

                // … rollback the transaction and do some reporting

                session.RollbackTransaction();

                throw exception;

            }

            finally

            {

                if (session != null)

                {

                    session.Close();

                }

            }

        }

 

        public static CogObjectStoreItem Load(object Id)

        {

            ISession session = null;

            try

            {

                // make sure there is a schema to read from.

                if (Context.Repository.SchemaForType(typeof(CogObjectStoreItem))==null)

                {

                    return null;

                }

 

                //acquire a session

                session = Context.Repository.CreateSession();

 

                // … and load the object

                return (CogObjectStoreItem)session.Load(Id);

            }

            catch (ElektroPostException exception)

            {

                // … do some reporting

                throw exception;

            }

            finally

            {

                if (session != null)

                {

                    session.Close();

                }

            }

        }

        public override string ToString()

        {

            return this.id.ToString();

        }

 

    }

}

The Conclusion

ObjectStore seems like a kind of Hibernate surrogate, the cool thing is that you can create the stored data without modifying the database schema, the not so cool is that there may be a serious penalty for bigger structures and I suspect there might be issues with speed for large data sets since the searching technique implemented seems to require that the objects be de-serialized to be checked if the match the filter.

Mateusz is going to test its performance over the following days to decide if it’s going to perform with what we need it for and I’ll try to see if I can get some hints for solving our problem on the EPiServer developer forums. But then again, even if it’s nto going to be our solution it may still prove useful for other issues.

Posted in C#, EPiServer
1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.50 out of 5)
Loading...
| 27 Comments »

Since IIS on XP seems to be handling only one site at a time and I have multiple installations of EpiServer for different purposes on my machine I needed a fast way of switching between them.

Sure I could go to the administration console and do it manually, but hey, why waste 30 seconds every time you do it when you can actually batch waste them in a chunk of half an hour to automate it.

so here’s my findings.

The adsutil.vbs is the script you want to get intalled on your system somewhere in the search path. %systemroot% will do.
You will find the script on your XP CD in the \i386 folder. Unpack with the following command:

expand E:\i386\adsutil.vb_ %SystemRoot%\adsutil.vbs

Assuming that E: is your CR-ROM drive.

You can find the user’s reference for the script on the Microsoft page

You may want to make sure that your Episerver is running in the default location by using the following call:

Cscript.exe %SystemRoot%\adsutil.vbs SET /W3SVC/1/ROOT

But since you’re probably having only one web server running on your machine anyway (why would you read it otherwise) probably the only thing you really need to do is:

Cscript.exe %SystemRoot%\adsutil.vbs SET /W3SVC/1/ROOT “C:\Inetpub\MyEPiServer###”

Another great tool I use that’s actually built into windows is reg.exe. this tool actually allows you to modify registry from command line. this was actually my initial approach to changing the path. It didn’t succeed to actually change the IIS root – but still it did the modification to the registry (that IIS just merrily ignored).

reg.exe ADD “HKLM\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\Virtual Roots” /v “/” /d “C:\Inetpub\MyEPiServer###,,201” /t REG_SZ /f

This is however good for changing some database settings if anything is stored in the registry before restarting the IIS, which is can be scripted as:

net stop W3svc
net start W3svc

So to summarize… my script for switching sites ends as:

@echo off

set root_folder=C:\Inetpub\MyEPiServer2\
set adscript_location=%SystemRoot%\adsutil.vbs

echo Switching IIS to %root_folder%
Cscript.exe %adscript_location% SET /W3SVC/1/ROOT “%root_folder%”
net stop W3svc
net start W3svc

Posted in ASP.NET, EPiServer, Internet Information Services
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...
| 9 Comments »

Google Map Control and why EPiServer is so cool!

I’ve recently had a chance to write a Google Maps control for EPiServer, it’s still somewhat buggy and I’m still considering how to release it since it still contains some java script that is potentially GPL infected and I would not like to contaminate someone’s code with it. I may end up rewriting it to some extent or make it more server side so that it’s completely ASP based.

Anyway…

We’ve started working on the rewrite of our site internally in a few CMS’es basically creating an internal competition on which of the engines/teams can do the best the easiest and the fastest site. I can say honestly, EPiServer has been a blast! Virtually any control we’ve decided to place there was almost completely effortless. The controls that are delivered (with sample usage on the demo site) just seem to cover everything. Well, almost everything. There is no map creation component as far as I can tell.

I’ve been wanting to write this control for quite a while and since I deployed a wiki for my family and started filling it in. I had a really nice experience with this Google Map extension to the MediaWiki. I wanted us to have the same on our site. And in the mean time we’ve started running into some limitations that required us to write some plugins for the editor’s site of the CMS. Striking two birds with one stone, here comes the Google Maps for EpiServer.

Anyone familiar with EpiServer knows that the CMS allows you to define the content on any given page through a set of properties defined for its page type. There is a handful of those, and each of them comes with a specific editor. Some of them even come with so called DOPE (Dynamic-on-page-editing). This feature is really so cool that by itself it’s probably one of the driving selling factor. I wanted it all!

To deliver it you need to inherit a property, (in my case I decided to go with a LongString as I can easily go over the 255 char limit if the user woudl decide to have more than a couple of flagpoints on his/her map) and define its editors.

I’ve found out that the property can be easily integrated with the CMS (virtually without any user intervention) by means of attributes/reflection. So here we go:

namespace Cognifide.EPiServerControls.GoogleMaps

{

  [global::EPiServer.PlugIn.PageDefinitionTypePlugIn(

    DisplayName = “GoogleMapData”, Description = “Google Map”)]

  public class GoogleMapProperty : EPiServer.Core.PropertyLongString

  {

   …

  }

}

Yay! one line of code and my class is a property and will show up in the system as one of the available data formats. Now how cool is that!?

The cool part of it is that now as it’s a property, it’s even easier to integrate it with the page.

<%@ Page language=”c#” Codebehind=”GoogleMapsPage.aspx.cs”

    AutoEventWireup=”True”

    Inherits=”development.Templates.GoogleMapsPage”

    MasterPageFile=”~/templates/MasterPages/MasterPage.master” %>

 

<%@ Register TagPrefix=”EPiServer”

    Namespace=”EPiServer.WebControls” Assembly=”EPiServer” %>

 

<asp:ContentContentPlaceHolderID=”MainRegion” runat=”server”>

  <EPiServer:Property ID=”MyGoogleMap” runat=”server”

  PropertyName=”GoogleMapData” />

</asp:Content>

That’s it! The CodeFile is practically empty, except for the autogenerated part. The property instance knows by itself that is should pull the data from the page property defined in “PropertyName”!

The control supports all 3 modes:

View Mode – obviously:

Google Map View

Edit mode – can’t do without it:

Google Map View

I initially planned to put the dope-like editing there but for some reason EPiServer scripts kept interfering with the JavaScript defined for the control. Didn’t give it too much thought though what I really wanted to work good is…

DOPE mode – this is probably the coolest thing in the whole deal:

Google Map View

The only problem I still have with the last mode is that most of the code for the DOPE mode I have is a modified version of what comes originally from the MediaWiki Google Map extension. Since JavaScript is not my core competence, I’ve only modified it to the extent that was needed for the code to work and therefore before save, you need to copy the dynamically generated code that’s just below the editing controls and into the edit box. Lame, I know. But I don’t really fancy learning Java Script further right now and it was not the point of this exercise. Perhaps if the control is released someone will be kind enough to fix and extend it so that it’s more streamlined.

Cognifide
The article is based on the knowledge I’ve gathered and work I’ve performed for Cognifide. Cognifide is an official partner EPiServer and the real contributor of the the control.

Posted in .Net Framework, ASP.NET, C#, EPiServer, Web applications
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...
| 24 Comments »

Microsoft loves programmers

I’ve just read a blog about a few new additions to C# 3.0 and in the context of what we’ve already learned about the whole “Orcas” project that is the simplest conclusion.

Microsoft .Net Framework designers and coders are just a bunch of programmers who you can clearly see enjoy hat they do. I can’t stress enough how many times I’ve been annoyed to be forced to wrap some private variables in the obvious public properties. No longer!

Instantiating a class followed by a bunch of setting of properties? Now done in one line. Shweet.

One may argue that C# is a set of such syntactic sugar. But then again, I am sure that’s why so many programmers really like it. Even some of the most Java oriented programmers (Yes Albert I’m looking at you!) in our company are looking forward to work on .Net.

It is the general perception here that, comparing to Eclipse, Visual Studio is a weak IDE in terms of pure code-writing-helpers, refactoring, and discovery of code dependencies. Only the next version will even be able to target more than 1 .net framework version… Please fix that crap… But the language designers are continually doing a great job.

Have a read on some:

Microsoft ,may be the most annoying company in any other context, though you can’t help but to feel that sweet and sticky loving goo leftover on your cursor avery time you flip a page….