Monday, December 7, 2009

ASP.NET MVC WebForms vs Spark View Engines. Part 2. Markup

In my previous article (ASP.NET MVC WebForms vs Spark View Engine. Part 1) I had started to describe the differences between standard ASP.NET MVC View Engine and spark. In this short article I will just show the differences between implementation of 3 equal pages.
So, less words, more code…

Master page

This is a general master page of a site – without parent master page with only some sections and common controls.
Web Forms implementation:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<%@ Import Namespace="Cmp.Web.Common.Extensions"%>
<%@ Import Namespace="MvcSiteMap.Core.Helpers"%>
<%@ Import Namespace="Resources"%>
<%@ Import Namespace="Cmp.Web.Controllers.Constants"%>
<%@ Register TagPrefix="controls" TagName="MainMenu"
Src="~/Views/Shared/Controls/Common/MainMenuControl.ascx" %>
<%@ Register TagPrefix="controls" TagName="MySolutionsPanel"
Src="~/Views/Shared/Controls/Common/MySolutionsPanelControl.ascx" %>
<%@ Register TagPrefix="controls" TagName="Login"
Src="~/Views/Shared/Controls/Common/LoginBarControl.ascx" %>
<%@ Register TagPrefix="controls" TagName="Search" Src="~/Views/Shared/Controls/Common/SearchControl.ascx" %>
<%@ Register TagPrefix="controls" TagName="Footer" Src="~/Views/Shared/Controls/Common/FooterControl.ascx" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<script src="<%= Url.Content("~/Scripts/Common.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/jquery-1.3.2.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/jquery.qtip-1.0.0.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/jquery.validate.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcJQueryValidation.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/slide.js")%>" type="text/javascript"></script>

<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
</head>

<body>
<div id="header">
<div id="logo_holder">
<div id="logo"></div>
</div>
<div id="login">
<controls:Login runat="server" />
</div>

<controls:MainMenu runat="server" />      
<controls:MySolutionsPanel runat="server" />
<controls:Search runat="server" />

<div id="breadcrumb">
<%= Html.BreadCrumbs() %>
</div>
</div><!--header-->

<div id="content">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div><!--content-->

<div id="footer">
<controls:Footer runat="server" />
</div><!--footer-->
</body>
</html>
Spark implementation:
<use namespace="Cmp.Web.Common.Extensions" />
<use namespace="MvcSiteMap.Core.Helpers"/>
<use namespace="Resources"/>
<use namespace="Cmp.Web.Controllers.Constants"/>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >

<script src="${Url.Content("~/Scripts/Common.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/jquery-1.3.2.min.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/jquery.qtip-1.0.0.min.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/jquery.validate.min.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/MicrosoftAjax.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/MicrosoftMvcAjax.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/MicrosoftMvcJQueryValidation.js")}" type="text/javascript"></script>
<script src="${Url.Content("~/Scripts/slide.js")}" type="text/javascript"></script>

<head runat="server">
<title><use content="TitleContent"/></title>
</head>

<body>
<div id="header">
<div id="logo_holder">
<div id="logo"></div>
</div>
<div id="login">
<use file="Common/LoginBarControl.spark" />
</div>

<use file="Common/MainMenuControl.spark" />      
<use file="Common/MySolutionsPanelControl.spark" />
<use file="Common/SearchControl.spark" />

<div id="breadcrumb">
${Html.BreadCrumbs()}
</div>
</div><!--header-->

<div id="content">
<use content="MainContent" />
</div><!--content-->

<div id="footer">
<use file="Common/FooterControl.spark" />
</div><!--footer-->
</body>
</html>
As you can see. In this simple case the pages are almost identical. There are some little differences in how to define controls and content place holders, and absence of runat=”server” attributes in Spark implementation. Also Spark code seems less in size and thus a little bit more clean.

Nested master page

This Master Page is an inheritor from the one shown above.
Web Forms Engine implementation:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" MasterPageFile="~/Views/Shared/MasterPages/OneColumn.Master" %>

<%@ Register TagPrefix="controls" TagName="Catalogue" Src="~/Views/Shared/Controls/Common/CatalogueControl.ascx" %>

<asp:Content runat="server" ContentPlaceHolderID="TitleContent">
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
</asp:Content>

<asp:Content runat="server" ContentPlaceHolderID="MainContent">
<div id="catalogue">
<controls:Catalogue ID="_catalogue" runat="server" />
</div>
<div id="main-area">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</asp:Content>
Spark implementation:
<use master="OneColumn" />

<content name="TitleContent">
<use content="TitleContent"/>
</content>

<content name="MainContent">
<div id="catalogue">
<use file="Common/CatalogueControl.spark" />
</div>
<div id="main-area">
<use content="InnerMainContent"/>
</div>
</content>
Again: Spark is more economic in terms of space. But nothing peculiar.

Simple page

Home page of the application.
Web Forms Engine:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/MasterPages/OneColumnWithTree.Master"
Inherits="System.Web.Mvc.ViewPage<Cmp.Models.HomeModel>" %>
<%@ Import Namespace="Cmp.Web.Constants"%>

<%@ Register TagPrefix="cms" TagName="HomeControl" Src="~/Views/Shared/Controls/Cms/Home/HomeControl.ascx" %>

<%@ Import Namespace="Cmp.Web.Controllers.Constants" %>
<%@ Import Namespace="Cmp.Web.Common.Extensions" %>
<%@ Import Namespace="Resources" %>
<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
<%= Strings.HomeIndexPageTitle %>
</asp:Content>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<div id="main-area">
<div id="home-login" style="background: url(<%= Url.ThemeContent(Images.HomeBackground)%>) no-repeat 5px 5px;">
<% if (Request.IsAuthenticated)
{ %>
Links
<% }
else
{ %>
<div id="home-login-box">
<% Html.RenderPartial(Url.Content(ControlUrls.LoginBoxControl), Model.AuthModel); %>
</div>
<% } %>
</div>
<cms:HomeControl runat="server" />
</div>
</asp:Content>
Spark:
<use master="OneColumnWithTree" />
<use namespace="Cmp.Web.Constants"/>
<use namespace="Cmp.Web.Controllers.Constants" />
<use namespace="Cmp.Web.Common.Extensions" />
<use namespace="Resources" />
<use namespace="System.Web.Mvc.Html" />
<viewdata model="Cmp.Models.HomeModel"/>

<content name="TitleContent">
${Strings.HomeIndexPageTitle}
</content>
<content name="InnerMainContent">
<div id="main-area">
<div id="home-login" style="background: url(!{Url.ThemeContent(Images.HomeBackground)}) no-repeat 5px 5px;">
<if condition='Request.IsAuthenticated'>
Links
</if>
<else>
<div id="home-login-box">
<use file="Common\LoginBoxControl.spark" Model="ViewData.Model.AuthModel"/>
</div>
</else>
</div>
</div>
</content>
This is more interesting. I like Spark here more than standard engine: it’s more compact, HTML-like, without mess of brackets and code, it has some HTML-like directives that could be used for partial rendering. Conditions borders clearly viewed. Moreover we could write conditions code into the tag via if-attribute and make code even more simpler.

Interim conclusions

We don’t have too complex pages in out project, so these samples were reliable and enough for my investigation. And based on I liked Spark more then Web Engine despite some learning curve and lack of best practices published. Existence of Partial rendering, Theming, Localisation and other samples also is a big plus for Spark. So, for me, after two parts of investigation Spark is just little bit better if you start from scratch, and not so good if your team is too good in Web Forms.

kick it on DotNetKicks.com
Vote on DZone: http://www.dzone.com/links/aspnet_mvc_webforms_vs_spark_view_engines_part_2.html

1 comment:

Aykut said...

You said you were gonna give some performance comparison info in your previous post.
Will there be a 3rd post?
Thanks.