I am setting up a page and sub-page system for a site. So, let’s say there is an “Index” page, with a “Sub” page. To access the sub page the URL would look like this: “Index/Sub”.
There could another page with “Sub” for the URL part. IE: “Index/Sub” and “AnotherPage/Sub”.
In ASP.NET MVC, I am taking a URL and splitting it into an array on forward slashes. Then I use EF4.1 to find the correct page entity.
As I look at the code, it works, but I’m wondering if I can reduce the number of calls to the database. Here’s my test action:
public string Index(string url)
{
// split url into array
string[] slugs = url.Split('/');
string currentSlug = slugs[0];
// set starting page and loop
Page page = db.Pages.FirstOrDefault(x => x.Slug == currentSlug);
for (var i = 1; i < slugs.Count(); i++)
{
if (!string.IsNullOrEmpty(slugs[i])
&& page != null
&& page.Children != null)
{
page = page.Children.FirstOrDefault(x => x.Slug == slugs[i]);
}
}
// if null return 404
if(page == null) throw new HttpException(404, "HTTP/1.1 404 Not Found");
// return page
return page.Label;
}
Is this scary or alright? Is there a way to reduce the potential number of db calls?
-Thanks for any tips-
Edit
Here’s my Page model FYI
public class Page
{
public Guid PageId { get; set; }
[Required(ErrorMessage = "URL is required")]
[StringLength(30, ErrorMessage = "Must be less than 30 characters")]
public string Slug { get; set; }
[Required(ErrorMessage = "Label is required")]
[StringLength(30, ErrorMessage = "Must be less than 30 characters")]
public string Label { get; set; }
[StringLength(100, ErrorMessage = "Must be less than 100 characters")]
public string Title { get; set; }
[StringLength(255, ErrorMessage = "Must be less than 255 characters")]
public string Keywords { get; set; }
[StringLength(300, ErrorMessage = "Must be less than 300 characters")]
public string Description { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public string LayoutName { get; set; }
public virtual ICollection<Content> Contents { get; set; }
public virtual Page Parent { get; set; }
public virtual ICollection<Page> Children { get; set; }
}
I’d certainly include the full page path on each
Page, so you can do the query in one db call. (Yes, then the data will not be fully normalised in the DB, but that a sacrifice we sometimes have to make for the sake of performance). Just make sure you have a strategy to update sub pages when ever a parent page changes.If you dislike the idea of a full path column on the pages, perhaps you should cache the paths and the page ID’s they resolve to, instead of asking the DB each time (Remember to have a cache clearing strategy).