Refactoring the archive page


Published: 7/5/2012, Author: Håkan Edling Categories: Tutorials, Piranha, 0 Comments

In this post we'll take the Blog archive page we built in the last post and refactor it by moving the inline code into a custom model and then finally creating a new page implementation.

Before we go any further and start refactoring our archive page, make sure you read the previous post where we created the archive page.

If you now take look at the top of the default Page.cshtml in your Piranha project you'll see the following line:

@inherits Piranha.WebPages.SinglePage

The SinglePage class is the base-class of all templates that represents a page in the site, and it handles the loading of all data from the CMS-part of the framework. The SinglePage has a strongly typed Model which holds all of the available data for the current page. The first thing we're going to do is to create our own Model to use in this page to encapsulate the extra data we want, so let's add a class name BlogStartModel.cs in our App_Code directory and add the following properties.

public class BlogStartModel : Piranha.Models.PageModel {
public int? Year { get ; set ; }
public int? Month { get ; set ; }
public bool IsArchive { get { return Year.HasValue ; } }
public List<Piranha.Entities.Post> Posts { get ; set ; }

// Default constructor.
public BlogStartModel() {
Posts = new List<Piranha.Entities.Post>() ;
}
}

So, now we've encapsulated all of the extra fields we worked with in our archive page from the previous post. Now let's take it a step further by adding a method to our model that loads the current posts so we can get that logic away from the view template.

public class BlogStartModel : Piranha.Models.PageModel {
...

public void LoadPosts() {
  using (var db = new Piranha.DataContext()) {
     var query = db.Posts.
Include("CreatedBy").
Include("Categories").
       Where(p => p.Template.Name == "Blog post") ;
        
      if (Year != null && Month != null) {
       var start = new DateTime(Year.Value, Month.Value, 1) ;
       var stop = start.AddMonths(1) ;
        query = query.Where(p => p.Published >= start && p.Published < stop) ;
      } else if (Year != null) {
       var start = new DateTime(Year.Value, 1, 1) ;
        var stop = start.AddYears(1) ;
        query = query.Where(p => p.Published >= start && p.Published < stop) ;
      }
      Posts = query.OrderByDescending(p => p.Published).ToList() ;
    }    
}
}

Allright, neat and clean! Now let's just update our view to use our BlogStartModel instead of the standard PageModel and then update our inline code a bit. After we've done this our archive page should look something like this.

@inherits Piranha.WebPages.SinglePage<BlogStartModel>
@{
if (UrlData.Count > 1) {
   try {
     Model.Year = Convert.ToInt32(UrlData[1]) ;
    } catch {}
}
if (UrlData.Count > 2) {
   try {
     Model.Month = Convert.ToInt32(UrlData[2]) ;
    } catch {}
  }
  Model.LoadPosts() ;
}

That looks a whole lot more organized than before, doesn't it. And better yet, by moving our code away from the view we have now made sure that we can apply unit testing to our model. But we're not done yet, let's now move the final rows of code away from our view into our own custom Page implementation. We'll start off by adding a new class BlogStart.cs in our App_Code directory.

public abstract class BlogStart : Piranha.WebPages.SinglePage<BlogStartModel> {
  protected override void ExecutePage() {
   if (UrlData.Count > 1) {
     try {
       Model.Year = Convert.ToInt32(UrlData[1]) ;
      } catch {}
    }
    if (UrlData.Count > 2) {
     try {
       Model.Month = Convert.ToInt32(UrlData[2]) ;
      } catch {}
    }
    Model.LoadPosts() ;
  }
}

As you can see we've moved the remainder of the code into the ExecutePage method. This method is executed after the CMS data has been loaded, but before any possible event-handlers kicks in, much like Page_Load in WebForms.

Finally, let's change our view to inherit from our new BlogStart class instead of the standard SinglePage class and remove all of the code from our view.

@inherits BlogStart
@{
// Nothing here no more :-)
}

Hopefully you've now learned how to both create an archive page and how to create custom models and page implementations for your templates. Happy hacking!


blog comments powered by Disqus