Getting started

This "getting started" is based on VS2008. All tutorials are included in the source distribution

Simple MVC tutorial

Requires ASP.NET MVC
First we create a new MVC solution.

New project in VS2008 of the 'ASP.NET MVC Web Application' type

We now add a reference to the 'org.SharpTiles.dll'

Add Reference > Browse > org.SharpTiles.dll

To use the tiles view engine you have to register the TilesViewEngine. A good place to do this is in the Application_Start method in Global.asax.cs extension methods.

protected void Application_Start()
{
  RegisterRoutes(RouteTable.Routes);
  ViewEngines.Engines.Clear();
  ViewEngines.Engines.Add(new TilesViewEngine().Init());
}

You don't have to change anything to your Controller. (This was required in older release of SharpTiles.)

using System.Web.Mvc;
using org.SharpTiles.Connectors;

namespace MvcApplication1.Controllers
{
  public class HomeController : Controller
  {
    public ActionResult Index()
    {
      ViewData["Title"] = "Home Page";
      ViewData["Message"] = "Welcome to ASP.NET MVC!";

      return View();
    }

    public ActionResult About()
    {
      ViewData["Title"] = "About Page";

      return View();
    }
  }
}

Well we are done with the code files lets move on to configuring tiles. SharpTiles requires a tiles definition file which holds all definitions. You can either set the location in the Web.Config file or just make a file called tiles.xml as embedded resource and place it in your assembly. SharpTiles will scan the calling assembly looking for a tiles.xml file. For now we will use the assembly approach. Check out the tutorial section for different approaches. So lets make the file tiles.xml in the Views folder. Make sure it is an embedded resource. It should look like this:

<?xml version="1.0" encoding="utf-16"?>
<tiles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <definitions>
    <tile name="Home.Index" path="Views.Home.Index.tile" />
    <tile name="Home.About" path="Views.Home.About.tile" />
  </definitions>
</tiles>

In the sample file we see two view names 'Home.Index' and 'Home.About' (in italic). The default tile name is a concatenation of the controller name, a '.', and the action name (<controller>.<action>). The highlighted blue parts are the tiles we have to implement. First we construct an Index.tile in Views\Home

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
      <title>Index</title>
  </head>
  <body>
    <h1>${Title}</h1>
    <p>${Message}</p>
    <a id="link_to_about" href="Home/About">Next</a>
  </body>
</html>

And we make an About.tile in View\Home

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
      <title>Welcome</title>
  </head>
  <body>
    <h1>${Title}</h1>
    <p>Lorem ipsum dolor sit amet,
       consectetuer adipiscing elit, sed diam nonummy
       nibh euismod tincidunt ut laoreet dolore magna
       aliquam erat....</p>
  </body>
</html>

Make sure that the you make both files an 'Embedded Resource'. This should result in the following file structure. The .aspx files can be removed, if you like.

File structure after completing previous steps

Voila, you are ready to run the solution.

Application showing the home screen

I can almost hear you think: "Hmmm wait a minute. I've lost my master page. Now I'm repeating myself. This can't be good". And you are correct. This is where tiles come in the picture.

Adding Tiles

What we're missing here is the base page. Let's introduce it again without together with our tile place holder. Create a file 'Layout.tile' in the 'Shared' folder with the following contents. Make sure that the you make it an 'Embedded Resource' and change your virtual path in you project settings to ''/SharpTilesSample/'

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>${Title}</title>
    <link href="/SharpTilesSample/Content/Site.css"
          rel="stylesheet"
          type="text/css" />
  </head>
  <body>
    <div class="page">

      <div id="header">
        <p id="logo">
          <a href="">My Sample MVC Application WITH TILES</a>
        </p>
        <ul id="menu">
          <li>
            <a id="menu_to_index"
               href="/SharpTilesSample/Home/Index">Index</a>
          </li>
          <li>
            <a id="menu_to_about"
               href="/SharpTilesSample/Home/About">About</a>
          </li>
        </ul>
      </div>

      <div id="main">
        <div id="content">
          <tiles:insert name="body"/>
        </div>
        <div id="footer">
          <p>
            My Sample MVC Application WITH TILES © Copyright 2008
          </p>
        </div>
      </div>
    </div>
  </body>
</html>

As you can see I highlighted all url's, (your first) SharpTiles insert tag and ${Title}. The <tiles:insert/> is the will be substituted with the content defined in the tiles.xml For now you can think of it as the <asp:ContentPlaceHolder ID="MainContent" runat="server" /> on steriods. I will explain later.

The urls are highlighted because they have to absolute and include the application name. If you don`t want to mention the application name you got to use the <c:url/> tag. The next example shows the same menu as above but now with the use of the <c:url/>.

          <li>
            <a id="menu_to_index"
               href="<c:url value='~/Home/Index'/>">Index</a>
          </li>
          <li>
            <a id="menu_to_about"
               href="<c:url value='~/Home/About'/>">About</a>
          </li>

Okay we got rid of the repeating of the application name, but (in my opnion) we do pay a small price. The single quote is required for parsing purposes.

So what's next. We got our new layout template in place. But our view 'Index' and 'About' still have the redudant html stuff in it. After some stripping the Index.tile should look like this

<h1>${Title}</h1>
<p>${Message}</p>
<a id="link_to_about" href="/SharpTilesSample/Home/About">Next</a>

And the About.tile should look like this

<h1>${Title}</h1>
<p>
  Lorem ipsum dolor sit amet,
  consectetuer adipiscing elit, sed diam nonummy
  nibh euismod tincidunt ut laoreet dolore magna
  aliquam erat....
</p>

Now we can put it all together. To make this all work we have to revisited the tiles.xml and redefine the 'Index' and 'About' definition. What do we need to define:

  • Define the tile 'Layout.tile' as 'Default.Page.Layout'
  • Extend the tile 'Home.Index' from 'Default.Page.Layout'
      And use 'Index.tile' for the 'body' attribute.
  • Extend the tile 'Home.About' from 'Default.Page.Layout'
      And use 'About.tile' for the 'body' attribute.

Why is 'Index' extended from 'Default.Page.Layout'? We want the 'Index' file to use the same layout as defined in 'Default.Page.Layout'. Extending takes care of this.

<?xml version="1.0" encoding="utf-16"?>
<tiles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <definitions>
    <tile name="Default.Page.Layout" path="Views.Shared.Layout.tile" />

    <tile name="Home.Index" extends="Default.Page.Layout">
      <attribute name="body" value="Views.Home.Index.tile"></attribute>
    </tile>

    <tile name="Home.About" extends="Default.Page.Layout">
      <attribute name="body" value="Views.Home.About.tile"></attribute>
    </tile>

  </definitions>
</tiles>

And yet again you are ready to run the solution.

Application showing the home screen now with a layout template

This looks alright, doesn't it. I promised you that the layout was testable, without running the webserver. This is covered in the next block. If testing through the webserver is your need I would suggest using WatiN or checkmate

Writing a test

To be able to use tiles in tests. The tiles definitions have to be loaded. SharpTiles provides some functionality to help writing tests. The GuardInit loads the embedded tiles inside the provided assembly. private IViewCache _cache;

[SetUp]
public void SetUp()
{
  _cache = new TilesCache().GuardInit(Assembly.GetAssembly(typeof(OutputConstraintTest)))
}

The tiles in the SharpTilesSample application our now loaded and available for testing(any IViewCache will do). The behaviour of the used cache differs. SharpTiles comes with the following two IViewCache implementations.

  • TilesCache - This cache preloads all the tiles from the tiles.xml View are retrieved by tile definition name.
  • NstlCache - This cache lazily loads all view. View are retrieved by path name.
Let's write a simple test, that checks the rendering of a complete tile.

Assert.That("Home.About"1,
  Output.
  Is.EqualTo.
  File("Views/Home/about.expected.full.html"2).
  UsingModel(new Hashtable { { "Title", "TEST TITLE" } }3)
  From(_cache)4);

  1. The tile to test
  2. The file location with the expected result
  3. The model to use for rendering
  4. The cache which contains all the tiles

Testing only an attribute of a tile can be achieved by <Tile name>@<Attribte name>. For example Home.About@body Testing the full rendering of a tile (and it's nested tiles) is specificly usesfull for tesing small tiles and for refactoring bigger tiles. See the chapter about Refactoring a test.
When testing a tile with nested tiles, you don't want full rendering. We only want to unit test the tile and not be bothered with nested tiles. Full rendering will make subject your tests to changes of used tiles and therefby unstable. How to prevent this problem. SharpTiles offers you a way to stub-out the used tiles.

Assert.That("Home.About",
  Output.
  Is.EqualTo.
  File("Views/Home/about.expected.tile.html").
  UsingModel(new Hashtable { { "Title", "TEST TITLE" } }).
  StubOutTiles().
  From(_cache));

SharpTiles also renders whitespaces, tabs, newlines, etc. This means that rendering a tile may add some unexpected white space characters. In HTML we're not so concerned white space characters. This can complicate unit testing. When Output.Is.Like is used instead of Output.Is.EqualTo al white space characters are ignored in the comparison.

This covers the basic of unit testing of tiles. Now you should be able to test driven develop and refactor the html rendering of your web application.

Refactoring

With testing available, refactoring is possible. The next tutorial shows how to extract a tile. First we capture the current output. We can do this by writing a test. If you download the source code you can use the tests inside the MVCSample application.

Assert.That("Home.About",
  Output.
  Is.EqualTo.
  File("Views/Home/about.expected.full.html").
  UsingModel(new Hashtable { { "Title", "TEST TITLE" } }).   StoreResultInFile(@"c:\output.html").
  From(_cache));

It's not advisable to keep this test. We only use it for refactoring. After running the test. The highlighted addition can be removed. Now we can start refactoring. We want to move the menu(high lighted in the sample below) on top a tile.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>${Title}</title>
    <link href="/SharpTilesSample/Content/Site.css"
          rel="stylesheet"
          type="text/css" />
  </head>
  <body>
    <div class="page">

      <div id="header">
        <p id="logo">
          <a href="">My Sample MVC Application WITH TILES</a>
        </p>
        <ul id="menu">
          <li>
            <a id="menu_to_index"
               href="/SharpTilesSample/Home/Index">Index</a>
          </li>
          <li>
            <a id="menu_to_about"
               href="/SharpTilesSample/Home/About">About</a>
          </li>
        </ul>
      </div>

      <div id="main">
        <div id="content">
          <tiles:insert name="body"/>
        </div>
        <div id="footer">
          <p>
            My Sample MVC Application WITH TILES © Copyright 2008
          </p>
        </div>
      </div>
    </div>
  </body>
</html>

To achieve this copy the high lighted section into a new file '/Views/Home/Shared/Menu.tile'. And replace the high lighted section in 'Layout.tile' with

<tiles:insert name="menu"/>

The tiles are changed but we have to inject a tile with name 'menu' into to the Layout.tile. This must be done in the 'tiles.xml'. Change the line

<tile name="Default.Page.Layout" path="Views.Shared.Layout.tile"/>

into

<tile name="Default.Page.Layout" path="Views.Shared.Layout.tile">
  <attribute name="menu" value="Views.Shared.Menu.tile"/>
</tile>

Running the unit test probably will fail. This is because the template engine also renders spaces, enters, tabs, etc. We can fix this by using Like instead of EqualTo. Like ignores all whitespace characters.

Assert.That("Home.About",
  Output.
  Is.Like.
  File("Views/Home/about.expected.full.html").
  UsingModel(new Hashtable { { "Title", "TEST TITLE" } }).
  From(_cache));

Voila the test is running and the refactoring is complete

Contact form fixed

I regret reporting that the contact form was broken for the last week. All mails send to us were corrupted(empty). So reported bugs in the last week are not received. I'm aware that the timing with regards to the monorail release isn't very handy. The contact form is fixed now. I apologize.

4 February, 2010

Monorail released M5

Monorail is released. The release also contains some minor fixes.

23 January, 2010

Monorail almost finished

Maikel Willemse is coding a Monorail view engine. It's available in the nightly release. A tutorial and a new release will be available shortly.

2 January, 2010

No more tiles.xml
(if you like)

A NSTL view engine is now available. You can do SharpTiles without having a tiles.xml. You will lose the power of dependency injection. If you are interested check out the tutorial page.

21 July, 2009

Developer M3 released

Fixed a couple of parse bugs. Cleaned up refreshing of resources, resource locations and registration of the TilesViewEngine. Wrote some tutorials
Ronald Dehuysser contributed the <tiles:insertTemplate/> and <tiles:putAttribute/> tag.

8 June, 2009

HtmlHelper wrapped II

Updated tag reference documentation.

5 April, 2009

Ready for MVC RC 2

SharpTiles is now ready to use with MVC RC 2.

6 March, 2009

HtmlHelper wrapped

The MVC HtmlHelper is now wrapped and can be used. For it's only available in the nightly build. When the documentation and new Tutorials are made a new release will be made.

22 December, 2008

Ready for Beta 1

SharpTiles is now ready to use with MVC Beta 1. The tutorial page will be updated soon.

3 November, 2008

We've got Tiles

It took me a bit longer than expected but Milestone 1 is reached. Tiles are now available.

23 July, 2008

First release

Finally, after some hard work my pet project is ready for its initial release. Here it is! Please give it some thoughts and feel free to add comments.

23 May, 2008

SID: PopUp 0