Book Image

ASP.NET MVC 2 Cookbook

Book Image

ASP.NET MVC 2 Cookbook

Overview of this book

ASP.NET MVC, one of the latest web development platforms from Microsoft, brings the power of MVC programming to ASP.NET development. It simplifies the task of application development and maintenance for developers. However, ASP.NET MVC is filled with so many features that developers end up looking for solutions to the many problems that are encountered in their routine development tasks.ASP.NET MVC 2 Cookbook will provide solutions for the very specific problems that are encountered while developing applications with the ASP.NET MVC platform. It consists of many recipes containing step-by-step instructions that guide developers to effectively use the wide array of tools and features of ASP.NET MVC platform for web development ASP.NET MVC Cookbook is a collection of recipes that will help you to perform your routine development tasks with ease using the ASP.NET MVC platform. In this book you will be walked through the solution to several specific web application development problems. Each recipe will walk you through the creation of a web application, setting up any Visual Studio project requirements, adding in any external tools, and finally the programming steps needed to solve the problem. The focus of the book is to describe the solution from start to finish. The book starts off with recipes that demonstrate how to work effectively with views and controllers – two of the most important ingredients of the ASP.NET MVC framework. It then gradually moves on to cover many advanced routing techniques. Considering the importance of having a consistent structure to the site, the book contains recipes to show how to build a consistent UI and control its look with master pages. It also contains a chapter that is packed with many recipes that demonstrate how to gain control of data within a view. As the book progresses through some exciting recipes on performing complex tasks with forms, you will discover how easy it is to work with forms to jazz up the look of your web site. Building large applications with ease is one of the prime features of the MVC model. Therefore, this book also focuses on tools and features that make building large applications easier to manage. As data plays an important role in the MVC architecture, there are ample recipes dedicated to cover data validation, access, and storage techniques. Finally, the book demonstrates how to enhance the user experience of your visitors by controlling the data at the application, session, caching, and cookie level. By the end of this book, you will have explored a wide array of tools and features available with the ASP.NET MVC platform
Table of Contents (16 chapters)
ASP.NET MVC 2 Cookbook
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface

Loading a view template from a database with NVelocity


In this recipe, we will take a look at a different view engine for the ASP.NET MVC framework called NVelocity. NVelocity is a very stable templating engine that has been around longer than the MVC framework has. It plugs into, and works quite nicely with, the ASP.NET MVC framework (as we will see). In this particular recipe, we will use NVelocity in a slightly different manner than just wiring in a different view engine. We will use NVelocity to render views directly from a database. This gives us templating abilities for rendering dynamic views, but this could also be used to render the contents of an e-mail, or any other template-driven blob of text.

Getting ready

As in the other recipes, we will start off with the ViewModel recipe, discussed earlier. Next, we need to grab a copy of the NVelocity library at http://www.castleproject.org/castle/projects.html. (I also put the library in the dependencies folder). You will need to have SQL Server Express installed to follow along with this recipe.

How to do it...

  1. 1. The first step to this project could be a number of things! Let's get started by adding a reference to the NVelocity library (NVelocity.dll) in the dependencies folder.

  2. 2. Next we need to set up a quick database to use in the steps ahead. Do this by right-clicking on the App_Data folder in your project and select Add a new item. Choose a SQL Server database. I named my database Templates.

  3. 3. Now in your Server Explorer window you should see under the Data Connections section a Templates.mdf entry. Expand that entry. Right-click on the tables folder and add a new table.

    • Set the first column of this table, to be called TemplateID, with a data type of int. Set this column to be a primary key (by clicking on the key icon above). And then set the identity specification (Is Identity) to be Yes.

    • Then add another column, called TemplateContent, with a data type of VarChar(MAX).

    • Add one more column called ViewName. This will be a VarChar(100) field. Save this table and call it Templates.

  4. 4. Then we will add LINQ to SQL to our project. Do this by right-clicking on the Models folder and select Add new item. Select the LINQ to SQL Classes entry and name it Template.dbml.

  5. 5. When the design surface opens, drag your Template table from the server explorer onto the design surface. Save that file and close it. Then build your project (this builds the TemplateDataContext class for you, which we will need in the following steps).

  6. 6. Right-click on the Templates.mdf entry in the server explorer and select Properties. In the Properties window, select and copy the entire connection string entry. It should look something like this:

    Data Source=.\SQLEXPRESS;AttachDbFilename={driveLetter}:\{pathToFile}\Templates.mdf;Integrated Security=True;User Instance=True
    
  7. 7. Now create a new class in the Models directory called TemplateRepository.cs. In this class, we will create a method called GetTemplateByViewName, which will be responsible for getting a template from the database by the template's name.

    Models/TemplateRepository.cs:

    public class TemplateRepository
    {
    public string GetTemplateByViewName(string ViewName)
    {
    string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename= {FilePathToDataBase}\Templates.mdf;Integrated Security= True;User Instance=True";
    string result = "";
    using(TemplateDataContext dc = new TemplateDataContext(connectionString))
    {
    Template template = (from t in dc.Templates where t.ViewName == ViewName select t).FirstOrDefault();
    result = template != null ? template.TemplateContent : "The requested template was not found for view " + ViewName;
    }
    return result;
    }
    }
    
  8. 8. Now we can create a class that will work with NVelocity to parse our template. Right-click on the Models folder and add a new class called TemplateService.cs. This class will have a method called ParseTemplateByViewName. This method will be responsible for interacting with the NVelocity view engine to parse a passed in template.

    Models/TemplateService.cs:

    public class TemplateService
    {
    public string ParseTemplateByViewName(string template, Dictionary<string,object> viewParams)
    {
    VelocityContext vc = new VelocityContext();
    foreach (var v in viewParams)
    {
    vc.Put(v.Key, v.Value);
    }
    //create the engine
    VelocityEngine ve = new VelocityEngine();
    ve.Init();
    //the output stream
    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    //merge the template
    ve.Evaluate(vc, sw, string.Empty, template);
    return sb.ToString();
    }
    }
    
  9. 9. Now we need to add some code to our HomeController. Let's start by creating a new action called AnotherProduct(). Inside this action, we will still utilize the creation of a Product and a Category. And we will use our ViewModel as our transport object, which will carry the Product and Category instance for us. Then we need to create a dictionary that will take the variables we used in the parsing of our template. Lastly, we will call our TemplateService to parse out the template that the TemplateRepository locates for us.

    Controllers/HomeController.cs:

    public ActionResult AnotherProduct()
    {
    Product p = Builder<Product>
    .CreateNew()
    .Build();
    Category c = Builder<Category>
    .CreateNew()
    .Build();
    ProductView pv = new ProductView();
    pv.CurrentCategory = c;
    pv.CurrentProduct = p;
    //define the variable context
    Dictionary<string, object> variableParams = new Dictionary<string,object>();
    variableParams.Add("ProductView", pv);
    ViewData["content"] = new TemplateService()
    .ParseTemplateByViewName(new TemplateRepository().GetTemplateByViewName("AnotherProduct"), variableParams);
    return View();
    }
    
  10. 10. Then you can create the AnotherView view. This will be an empty view that simply renders the content from within ViewData.

    Views/Home/AnotherProduct.aspx:

    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
    <%= ViewData["content"] %>
    
  11. 11. Lastly, before anything will actually come together, we need to add an entry into our database. The TemplateContent entry will look like this:

    <html><head><title>$ProductView.CurrentProduct.ProductName</title></head><body><h2>$ProductView.CurrentProduct.ProductName</h2>Hello world from an NVelocity template!</body></html>
    

    The ViewName will be AnotherProduct to match our AnotherProduct action.

  12. 12. Now you can start debugging by hitting F5 and see the results of our database-driven view.

How it works...

This is a simple modification to the way that NVelocity would normally work. In most cases, you would store your NVelocity templates on the file system or in the resource files. These are then read by a file-based template reader and parsed similarly to the fashion defined earlier. All that we did differently was grabbed our content from the database.

We have still piggybacked our implementation of NVelocity on top of the MVC framework and most importantly on top of the WebForms view engine. This means that we could use regular views for most of our pages, while templates from the database could be scattered about where we may want to have user-generated or easily administered content.

There's more...

Some people might complain about the choice to piggyback the NVelocity view engine on the back of the MVC framework and the WebForms view engine. However, think of the flexibility that you would have with this option when pulling your dynamic-view content from the database.

By using the WebForm's view engine on top of the MVC framework, you get all sorts of built-in features such as a master page, templated helpers, scaffolding support, and so on. Using the NVelocity engine you can then define the remainder of your content from the database. This means that rather than having a statically defined Product partial view that all of the products in your shopping cart catalog use, you could instead have a different Product layout for every product. Expand this thought a bit further so that you could call and parse many templates from the database for one view, allowing you to define NVelocity partial templates, such as a common Product header and footer, attributes layout, and so on. And now that all of this layout logic is persisted to the database, it can all be edited from the Web.

Note

What about performance? In a site with heavy load, the odds are that you would cache your database calls, page compilations, and so on. Only the output would ever actually be hit by every visitor of your site. No worries!

Replacing the default MVC view engine with NVelocity

If you are interested in replacing the default view engine (WebForms view engine) with NVelocity, have a look at the MVC Contrib (codeplex.com/MVCContrib) project. The guys at Headspring (headspringsystems.com) currently have various classes created that will allow you to override the MVC framework to use NVelocity as the primary view engine in the MvcContrib.ViewEngines.NVelocity.dll (currently).

Want to load templates in other ways?

While researching this particular recipe, I came across all sorts of ways to work with NVelocity. One demo went that extra step to show multiple ways to load templates in a very clean fashion. I put this demo in the code directory (included with the source of this book). You can find the original posting here: http://mihkeltt.blogspot.com/2009/12/nvelocity-template-engine-sample.html.

Want to use more than one view engine?

Javier Lozano has been putting together a product called MVC Turbine. One of its goals is to allow you to host content from many view engines at once (among many other cool things). Take a look here for more on that topic: lozanotek.com/blog/archive/2009/10/05/Multiple_View_Engines_with_MVC_Turbine.aspx.