technology from back to front

Archive for November, 2009

Introducing rabbitmq-status plugin

RabbitMQ is a becoming decent product, but it shares some of the common problems of young software – for example, beginners have a hard time understanding what happens under the hood. Don’t get me wrong, Rabbit generally works perfectly as a black-box. But at some point, when things go wrong or when Rabbit needs to be added to a monitoring infrastructure, it becomes necessary to understand more about the internals. This is when things get difficult.

I was wondering how we could address this issue and decided that Rabbit should serve a simple http status page similar to status pages that are known from Apache or Haproxy projects.

Read more…

by
marek
on
30/11/09

Performance testing RabbitMQ Streams

RabbitMQ Streams is our data streams management system that allows arbitrary routing, transforming, and merging of messages. We used a “quick and dirty” test framework during development to check there were no major performance issues, but we needed to improve on this to test the real configurations used by the BBC Feeds Hub.

Read more…

by
Lee Coomber
on

A Custom ASP.Net Navigation Component for EpiServer CMS

LShift have used the EpiServer CMS on several customer projects and it generally does most things you would want
to do with a CMS in a simple way. EpiServer is a .Net based CMS and if you understand ASP.NET templated pages and templated controls it is very straightforward with a minimal learning curve.

One challenge I faced on a recent project was to implement a particular HTML navigation design using EpiServer. The HTML design called for the navigation to be rendered as nested HTML lists with the current section of the site annotated with a particular class.

For example if you were looking at “Tasty Fish” in the “Cat Food” section of the site the HTML
should look something like this:

<ul>
 <li>Dog Food
      <ul>
          <li>Meaty Bones</li>
        </ul>
 </li>
 <li class="selected">Cat Food
     <ul>
          <li>Tasty Fish</li>
     </ul>
 </li>
</ul>

On initial inspection the EpiServer CMS appears to have two controls that may help, the EpiServer:MenuList and the EpiServer:PageTree. I first attempted to use the EpiServer:MenuList, this allowed me to do this:

   <ul>
      <li>Dog Food</li>
       <li>Cat Food</li>
   </ul>
 <ul>
      <li class="selected">Tasty Fish</li>
    </ul>

This isn’t quite what the design required, the complete site navigation tree needed to be rendered since CSS was being used to show and hide menus in response to mouse rollovers.

So for attempt two I tried the EpiServer:PageTree component; this component is designed to render a whole tree of pages so it should be an appropriate solution. It is a very flexible component and provides lots of templates for customising the layout based upon the state of the tree. This is what I ended up with:

 <ul>
      <li>Dog Food
          <ul>
              <li>Meaty Bones</li>
            </ul>
     </li>
     <li>Cat Food
          <ul>
              <li class="selected">Tasty Fish</li>  <!-- OH NO THIS IS WRONG -->
            </ul>
     </li>
 </ul>

This was very close! However it didn’t meet the design requirement; the top level item that contained the current page needed to be tagged with the CSS class, not the item corresponding to the current page. There didn’t seem to be an easy way to achieve this with the EPiServer components.

I decided I probably need some type of custom control, I then proceeded to write three implementations of a navigation control moving from sinful generation of HTML in a code behind, through my own templated control until arriving at the obvious solution using the asp:ListView control and a simple code behind. This was a nice solution because it uses a standard ASP.NET component in a standard way, the complication of tagging the selected top level item could be hidden away in a small code behind, and the markup was completely under the control of the HTML developer.

The navigation section of the ASP page looked like this:

   <asp:ListView ID="Level1" runat="server" ItemPlaceHolderID="Level1Item">
      <LayoutTemplate>
          <ul><asp:PlaceHolder ID="Level1Item" runat="server"/></ul>
        </LayoutTemplate>
     <ItemTemplate>
            <li class='<%# ((Boolean)Eval("Selected")) ? "selected" : "" %>'><%# Eval("Name") %>
                <asp:ListView ID="Level2" runat="server" ItemPlaceHolderID="Level2Item">
                  <LayoutTemplate>
                      <ul><asp:PlaceHolder ID="Level2Item" runat="server"/></ul>
                    </LayoutTemplate>
                 <ItemTemplate>
                        <li><%# Eval("Name") %>
                 </ItemTemplate>
               </asp:ListView>
           </li>
     </ItemTemplate>
   </asp:ListView>

This is a straightforward usage of nested ListViews and ASP data binding expressions, all of the markup is visible and it can be explained to an HTML developer in a short amount of time. New navigation levels can be added in exactly the same way that the Level 2 navigation was added to the Level1 navigation. The ternary operator within the data binding expression, class='<%# ((Boolean)Eval("Selected")) ? "selected" : "" %>', determines if the navigation item is selected, this is a standard mechanism for conditional rendering with ASP.NET data bound controls.

This was combined with a page behind like this:

 protected override void OnLoad(System.EventArgs e)
  {
       base.OnLoad(e);

     Level1.DataSource = BuildMenuItems();
       Level1.DataBind();
  }

   private List<MenuItem> BuildMenuItems()
   {
       List<MenuItem> menuItems = new List<MenuItem>();

        PageData homePage = GetPage(PageReference.StartPage);
       foreach(PageData child in GetChildren(homePage.PageLink))
       {
           if(child.VisibleInMenu)
         {
               MenuItem item = CreateMenuItem(child, true);
                item.Selected = findPage(CurrentPage.PageGuid, child);
              menuItems.Add(item);
            }
       }

       return menuItems;
   }

   private MenuItem CreateMenuItem(PageData page, Boolean includeChildren)
 {
       MenuItem item = new MenuItem(page.PageName);
        item.Url = page.LinkURL;

        if (includeChildren)
        {
           PageDataCollection children = GetChildren(page.PageLink);
           foreach (PageData child in children)
            {
               if (child.VisibleInMenu)
                {
                   item.Children.Add(CreateMenuItem(child, true));
             }
           }
       }

       return item;
    }

   private Boolean findPage(Guid id, PageData parent)
  {
       if (id == parent.PageGuid) return true;

     foreach (PageData page in GetChildren(parent.PageLink))
     {
           if (page.PageGuid == id)
            {
               return true;
            }
           if(findPage(id, page))
          {
               return true;
            }
       }

       return false;
   }

With a helper class MenuItem defined like this:

public class MenuItem
{
  public MenuItem(String name)
    {
       this.Name = name;
   }

   public String Name { get; set; }
    public String Url { get; set; }
 public Boolean Selected { get; set; }
   private List<MenuItem> children = new List<MenuItem>();
 public List<MenuItem> Children {
      get
     {
           return children;
        }
       set
     {
           children = value;
       }

   }

}

The page behind creates MenuItem instances for each page in the navigation. The top level item gets tagged as selected only if the current page is one of its children. This is a reasonable amount of code to write but it was the smallest solution that solved the problem and made the HTML obvious and available for modification by HTML developers.

by
tim
on
29/11/09

We are still recruiting

LShift is looking for senior developers. If you want to join one of the most skilled and interesting technical teams around, how about submitting a CV and some code samples?

LShift is built around the idea of having a team of highly skilled developers who combine a breadth and depth of outlook and experience. We do not recruit people to slot into a particular technical role with a particular set of tools. Instead we recruit all-rounders, familiar with a broad range of technologies and environments who have a good appreciation of all aspects of software engineering. All developers are required to act as client-facing project leads, managing all technical aspects of a project from its inception through to delivery.

If you think you’d fit then please read how to apply, then use our online application form.

by
Administrator
on
25/11/09

mercurial-server 0.8 released

mercurial-server home page

mercurial-server gives your developers remote read/write access to centralized Mercurial repositories using SSH public key authentication; it provides convenient and fine-grained key management and access control.

Read more…

by
Paul Crowley
on
10/11/09

Search

Categories

You are currently browsing the LShift Ltd. blog archives for November, 2009.

Feeds

Archives

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us