Introduction

Microsoft ASP.NET MVC framework follows a standard MVC pattern – Model contains data that will be shown, controller performs actions when some event happens, initializes model and passes it to the view, and view takes a model and renders HTML output that would be sent to the client browser. In the MVC 3 there are several view engines that can be used – standard ASP.Net view engine, Razor, Spark, NHaml etc. All of these view engines use different syntax for generating view, however they are all working in the same way – model is taken on the server-side, formatted using the template and HTML is sent to the client browser.
This article introduces a new concept of view engine – client-side view engine that renders a view in a client browser. In this concept, model and controller are still on the server-side. However, instead of the HTML, JSON is generated as an output from the server-side, it is accepted on the client-side and HTML is generated using the JavaScript templating engine.

Background 

This example shows how JavaScript templating engine in ASP.NET MVC project can be used instead of standard server-side templating engines. JavaScript templating engines use JSON objects as a model and generate HTML on the client side. Currently, there are several templating engines such as JQuery template, Pure, noTemplate, jsTemplate, Populate, or jTemplates, but this example uses JQuery loadJSON templating engine. JQuery loadJSON plugin is templating engine that binds JSON object into clean HTML template and generates view on the client-side. This is a simplest JavaScript templating engine that has all nessecary features to implement effective client-side templating engine.

Using the code 

In this article is presented code example where is demonstrated how can be used client-side view engine in ASP.NET MVC. Following sections show how JQuery loadJSON plugin can be integrated into the ASP.NET MVC application in order to replace standard server-side view engines. 

Model

Model is a class that contains information about Company. Source code of Company model class is given in the following listing:
    public class Company
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string Town { get; set; }
        public string Description { get; set; }
        public DateTime Date { get; set; }
        public string Contact { get; set; }
        public bool IsFeatured { get; set; }
        public string[] Country { get; set; }
        public string Logo { get; set; }
    }	 

Controller

Controller is not a standard controller that reacts on user action and returns view as it works in standard server-side view engines. In the JavaScript templating engines controller should return just a JSON objects that will be used as model on the client-side. This JSON object will be accepted in the JavaScript templating function and HTML output will be generated directly in the browser page.
This example has two required actions in the controller. First one action returns a list of companies and second one returns a single company by id. Source code of the controller is given in the following listing:

public class CompanyController : Controller
{
    public ActionResult List()
    {
       return Json(DataRepository.GetCompanies(), JsonRequestBehavior.AllowGet);
    }

    public ActionResult Data(int? ID)
    {
       return Json(DataRepository.GetCompanies().First(c => c.ID == ID), JsonRequestBehavior.AllowGet);
    }
} 

Action methods take model classes; format them as a JSON results and return JSON to the view engine. View engine on the client-side will call these actions when model is required by the view.

View 

When JavaScript templating engine is used, view can be a static page. You can use standard .aspx pages as views but the plain HTML page can be used as well. Given example has three view pages:

  1. List page where list of five companies is shown,
  2. Details page where single company details are shown,
  3. Edit page where information about single company are loaded into the form where details can be changed and posted to the server-side (although posting results is out of scope of this article). 

List page  

List page is used to define template that will be used to list companies in the browser. Static view page that is used in this example is shown in the following listing:

<html>
<head>
    <title>Listing JSON aray using the HTML template</title>
    <link rel="stylesheet" type="text/css" href="http://www.codeproject.com/Content/style.css" />
    <script src="http://www.codeproject.com/scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    <script src="http://www.codeproject.com/scripts/jquery.loadJSON.js")" type="text/javascript"></script>
    <script language="javascript" type="text/javascript">
        $(document).ready(function () {
        	$('li').loadJSON('/Company/List');
        });
    </script>
</head>
<body>
    <div id="page-wrap">
        <div id="contact-area">
            <ul>
                <li><a href="details.html" class="ID">
				<span id="Name" class="Name"></span>
			</a><span id="Address" class="Address"></span>
		  </li>
            </ul>
        </div>
    </div>
</body>
</html>

There is a plain HTML code placed in the unordered list, that defines item template that will be used to generate output. This part of the code is shown in the following listing:

<li>	
    <a href="details.html" class="ID">
	<span id="Name" class="Name"></span>
    </a>
	<span id="Address" class="Address"></span>
</li> 
 

Li tag contains HTML elements whose class attributes match the properties in the model class. View is initialized using the JavaScript line from the heading: 

$('li').loadJSON('/Company/List');   

This line loads JSON array from the /Company/List URL and loads it into the LI element. Company/List URL activates List method in the Company controller which returns a list of companies formatted as a JSON array. When loadJSON plugin gets applied on this element, properties of the objects are placed in the template. Moreover, this template item is replicated for each instance of the model in the array that is bound to the template. As a result, set of LI elements will be created representing a list of companies that are loaded from the /Company/List URL. You can find live example of list functionality here.

Details view 

Details page is used to show details about single company. It takes JSON object from the /Company/Details page and loads JSON object in the HTML template. Details page used in this example is shown in the listing below:

<html>
<head>
    <title>Displaying details of the single JSON object</title>
    <link rel="stylesheet" type="text/css" href="http://www.codeproject.com/Content/style.css" />
    <script src="http://www.codeproject.com/scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    <script src="http://www.codeproject.com/scripts/jquery.loadJSON.js")" type="text/javascript"></script>
    <script language="javascript" type="text/javascript">
        $(document).ready(function () {
	    var id = window.location.href.match("(ID=|id=|/)[0-9]+")[0].match("[0-9]+");
            $('div#data').loadJSON('/Company/Data/'+id);
        });
    </script>
</head>
<body>
<div id="page-wrap">
    <div id="contact-area">
	<div id="data">
	      <h1 id="Name"></h1>
              <img id="Logo" alt="" src=""/>
	      <label for="Address">Address:</label>
              <span id="Address"></span>
	      <label for="Contact">Contact by:</label>
              <span id="Contact"></span>
	      <label for="Town">Town:</label>
              <span id="Town"></span>
           <form action="edit.html" method="get">
              <input type="hidden" id="ID" name="ID"/>
              <input type="submit" value="Edit" class="submit-button"/>
           </form>
        </div>
    </div>
</div>
</body>
</html>

Page contains definition of blank HTML template with elements that have id attributes that match properties from the model. JavaScript call in the heading takes ID parameter from the page URL, and calls /Company/Details server-side page with that parameter. Controller action Details(int? ID) in the CompanyController will be called when this URL is sent to the server, and single company will be returned as a JSON result. This JSON object will be loaded in DIV with “data” id and elements in that DIV will be populated. You can see live example of the details page here.

Editing details 

Edit page is similar to the details page. However, here, single company record is loaded into the HTML form. Example of the edit page is shown in the following listing:

<html>
<head>
	<title>Load Form with JSON data</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link rel="stylesheet" type="text/css" href="http://www.codeproject.com/Content/style.css" />
	<script src="http://www.codeproject.com/scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
	<script src="http://www.codeproject.com/scripts/jquery.loadJSON.js")" type="text/javascript"></script>
        <script language="javascript" type="text/javascript">
            $(document).ready(function () {
             var id = window.location.href.match("(ID=|id=|/)[0-9]+")[0].match("[0-9]+");
             $('form').loadJSON('/Company/Data/' + id);
            });
        </script>
</head>
<body>
<div id="page-wrap">
    <div id="contact-area">	
        <form name="form_simple" id="form-simple" action="details.html" method="get">
            <input type="hidden" id="ID" name="ID" />
		<label for="Name">Name</label>
		<input name="Name" id="Name" type="text" />
		<label for="Address">Address</label>
		<textarea name="Address" id="Address" rows="5" cols="20"></textarea>
		<label for="Country">Country</label>
		<select name="Country" multiple="multiple">
                	<option value="">-</option>
			<option value="UK">United Kingdom</option>
                	<option value="SRB">Serbia</option>
			<option value="USA">United States of America</option>
			<option value="FRA">France</option>  
		</select>
		<label for="IsFeatured">Is Featured</label>
		<input name="IsFeatured" id="IsFeatured" type="checkbox" value="true"/>
		<label for="Town">Town</label>
		<select name="Town" id="Town">
                	<option value="" selected="selected">-</option>
			<option value="London">London City</option>
			<option value="Liverpool">Liverpool City</option>
			<option value="Lothian">Lothian City</option>
			<option value="Newcastle">Newcastle City</option>
                	<option value="Buckinghamshire">Buckinghamshire City</option>
                	<option value="Essex">Essex City</option>  
		</select>
		<label for="Contact">Contact</label>
			<input name="Contact" type="radio" value="Email"/> Email
			<input name="Contact" type="radio" value="Phone" /> Phone
			<input name="Contact" type="radio" value="Post" /> Post
            	<input type="submit" value="Details" class="submit-button" />
	</form>
    </div>
</div>
</body>
</html> 

Heading should contain JavaScript call that loads JSON object from the URL into the form. This JavaScript call is shown in the following code:

var id = window.location.href.match("(ID=|id=|/)[0-9]+")[0].match("[0-9]+");
$('form').loadJSON('/Company/Data/' + id); 

Result of this call is a form populated with properties of the JSON object loaded from the /Company/Data/<ID> URL. Live example of the form populated with the load JSON plugin can be found here and detailed rules that are used while populating form are described here.

Conclusion  

This article explains how loadJSON plugin can be used as a client-side templating engine, and it shows how JSON objects can be loaded directly in the HTML elements on the client side. There are several benefits of using the client-side templating engines:

  1. Performances – loading JSON objects from the server side, only minimal amount of data is transferred from the server to the client side. This way, it is not required to load unnecessary HTML tags from server and time required to load data is shorter.

  2. Caching – example uses static HTML pages as views. Therefore, if active views (e.g. .aspx pages) are used instead, they can be cached on the server side. This makes server-side response time shorter. 

  3. True separation of design and code – using server-side templating engines, code placed in the view is not completely clean. HTML code contains some elements that are required for binding server side data to the view elements. Examples in this article show that view is completely clean – there is nothing else except HTML code in the view pages (not even the custom attributes). 

However, this is not a “Holy Grail” of web development as it does not resolve all your problems, nor it represents the perfect solution. If you have some complex logic you need to place in the view, e.g. determining whether some element should be disabled or hidden, or if you need to dynamically show/hide some elements, you cannot implement this using the simple client side view engines. In such case, it is better to retain server-side code data because it will be easier to control it via code, partial views and server-side controls. However, applying client-side view engines (when this is appropriate) would bring you several benefits as explained above. 

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"