MVC - Expression Language and custom tags
I have seen several developers that want and have no problem by using server-side code blocks in a View when they are working with the MVC pattern. But I think the server-side code block should be used only in some advanced and special occasions and instead use an Expression Language. By using a lot of server-side code block can make the View messy and the solution can be difficult to implement, form the perspective of code maintainability and extensibility. If we instead use tags similar to HTML/XML we can make the code blend into HTML in a nice way.
Take a look at the following code:
<% if (ViewData != null && ViewData.HasError) {%>
...
<% } %>
<% if (ViewData.ExceptionType == ExceptionType.Critical) %>
<div class="criticalException">
Critical Error: <%= ViewData.ExceptionMessage%>
<% if (ViewData.InnerException != null) } %>
<%=ViewData.InnerException.Message%>
<% } %>
</div>
<% else %>
<div class="exception">
Error message :<br/><%= ViewData.ExceptionMessage%>
</div>
<% } %>
The above code is only used to demonstrate how messy a View can be when we have a lot of server-side code blocks. This code will not be easy for a designer or web developer to maintain. If we instead use an Expression Language (EL) and JSTL (JSP Stamdard Tag Library) for JSP in ASP.Net the View can be written like this:
<c:if test="${ViewData!=null && ViewData.HasError}">
...
</c:if>
<c:choose>
<c:when test="${ExceptionType == ExceptionType.Critical}">
<div class="criticalException">
Critical Error: <c:out value="${ViewData.ExceptionMessage}"/>
<c:out value="${ViewData.InnerException.Message}"/>
</div>
<c:otherwice>
<div class="exception">
Error message :<br/><c:out value="${ViewData.ExceptionMessage}"/>
</div>
</c:otherwice>
</c:choose>
The best part of the ${variable} is that it can evaluate null for us, and also do the type casting, so we don’t need to write:
<% if (ViewData.InnerException != null) } %>
<%=ViewData.InnerException.Message%>
<% } %>
or:
<%=ViewData.CustomerID.ToString()%>
Instead we simply write:
${ViewData.InnerException.Message}
${ViewData.CustomerID}
The best part, we shouldn't event need to use the ViewData, instead directly write:
${CustomerID}
Here is an example where a property path (sub-properties) is used:
${Order.Rows[1].Item.Price}
In some cases we need some more logic to test some conditions etc, something that can’t be placed inside of a Controller. This logic can instead of being a server-code block be capsulated into an own custom tag.
The problem with EL today is the lack of supports in tools, so we only get an error first at runt-time and some IDE don’t have support for easy handle the EL. To make it more powerful the tools need to handle it also. But I prefer this way instead of using server-side code block and I hope something similar will be added to the ASP.NET MVC Framework.
Nikhil wrote a post about using AJAX with the ASP.Net MVC Framework (only a prototype). He uses code like this:
<% RenderBeginAjaxForm(Url.Action("Add"),
new { Update="taskList, UpdateType="appendBottom",
Highlight="True",
Starting="startAddTask", Completed="endAddTask" }); %>
<input type="text" name="name" id="nameTextBox" />
<% Ajax.Watermark("nameTextBox",
new { watermarkText="[What do you need to do?]", watermarkCssClass="watermark"}); %>
<input type="submit" name="addTask" value="Add Task" />
<% RenderEndForm(); %>
The RenderBeginAjaxForm will render a <form> element with an onClick and onSubmit attribute etc. The RenderEndForm will also add a </form> The Ajax.Watermark is a way to extend a HTML element with a WaterMarker. I think this code is kind of “messy”. I would like to see some tags instead for example:
<ajax:Form Action="Add" Update="takstList" UpdateType="appendBottom" Hightlight="true" ...>
<ajax:waterMarkTextBox name="name" id="nameTextBox" markerText="[What do you need to do?]".../>
</ajax:form>
By using this solution, tags will be nicely blended into HTML and remove server-side code and make it easy for web developers (They are used to HTML element and attribute) to simple apply it and also maintain it. We can also easy see that we have a <form> and a </form>. This looks similar to Server controls today but this should be a more light-weight control, and the runat=”server” shouldn’t be used ;) This is similar to ViewComponent shipped with MonoRail (I think ;)), but I don’t like the declaration syntax MonoRail used. I prefer to use a HTML similar way to add components (custom tags) etc.
What kind of solution do you prefer?