views:

77

answers:

2

We have a small Asp.Net MVC project which displays a report of several tens or hundreds of rows of data. Each row is represented by an object on the view models.

Currently we are showing the rows like this:

<table>
   <tr style="text-align:center">
        <th>Name</th>
        <th>Item count</th>
        <th>Stat 1</th>
        <th>Stat 2</th>
        <th>Etc</th>
   </tr>
<%  var alternating = false;
    foreach(RowItem rowItem in Model.RowItems) 
    { %>
   <%= Html.BeginRow(alternating) %>
   <%= Html.ShowRow(rowItem) %>
   <% alternating = !alternating; %>
   <%= Html.EndRow() %>
   <% } %>
</table>

Where BeginRow, EndRow and ShowRow are helper extension methods that I wrote. ShowRow is something like

public static string ShowRow(this HtmlHelper html, RowItem rowItem)
{
   return "<tr><td>.... </tr>";
}

But I could also replace Html.ShowRow(rowItem) with another partial view, i.e. Html.RenderPartial("RowControl", rowItem);

The question is, what are the advantages and drawbacks of these two approaches? All I can think of is that the partial view is more "designable" - easier to work with when the amrkup is complex, and by team members who specialise in "design" and "client development", i.e. html, css and javascript not c#. The HTML helper method is a just assembling a string containing the required html, which appeals to an old-school coder.

Which one, if any, has noticeable performance implications over hundreds of items? Are there maintenability impacts for either of them? All other things being equal, which would you choose to use?

We are on Asp.Net MVC 1.0 and Visual Studio 2008, but will probably upgrade some time in the next few months.

A: 

When creating views for MVC projects, I generally try to keep all of the same element generation in the same view. So for your case, since you are creating a table, I would make sure that all table tags are created inside the same view. This helps ensure that you are creating well formed HTML and makes tracking down validation issues much easier.

I don't really like what is going on here so much for a couple of reasons. The show row extension is likely taking some kind of custom HtmlTableRow object as its input, which likely has a collection of HtmlTableCell objects in it, each of which has stylistic properties set on it. Since these HtmlTableRows are created in your controller, it tightly couples your presentation to your controller which defeats the separation of concerns principle of MVC.

Next, if you replace ShowRow with a render partial, it will not follow the guideline I suggest in the first paragraph by rendering tags for the same element in different views. Occasionally you can get away with rendering your elements in different functions, but if you do so, the objects they return should implement the disposable pattern and only be implemented with using statements.

If I were going to modify this so that designers could have more control over the design, I would render the table all in one partial view, and I would give every cell a descriptive class name. I would also take the entire table and put it in a partial view, even if it were the only thing on this page.

NickLarsen
As for the performance, that is something you should test for yourself in the profiler. Also keep in mind that performance is generally only an issue if people are complaining about performance. There is a famous quote about pre-mature optimization that someone could insert here.
NickLarsen
"The show row extension is likely taking some kind of custom HtmlTableRow object as its input, which likely has a collection of HtmlTableCell" - no, nothing of the sort. It takes a viewmodel object (For this example I have removed classes from the problem domain) and it returns a string. The controller send POCO ViewModels to stongly typed views. Returning HtmlTableRow from a controller just makes no sense at all.
Anthony
Well its good that your `Model.RowItems` is a view model, but you still end up with the same issue of pumping out incomplete html types from a function or view. By that I mean since it is not ok to have floating table rows hanging around outside of a table.
NickLarsen
Reading over my answer, I realize I may have not been very explicit about the advantages and disadvantages you asked about. I will update after dinner.
NickLarsen
+1  A: 

I'm not sure how well known this is (I just found out by playing around myself), but you can actually use anonymous methods to define chunks of your page content, so that is an alternative to defining a separate partial view. I find this especially useful when just have a small chunk of HTML/server code that I want to reuse, or if I don't want to define a complex Model/ViewData contract between a partial view and the calling view.

Below is an example of some code embedded in a view:

// define example data
IEnumerable<MyDataItem> data = new MyDataItem[] {
    new MyDataItem { Id = 1, Value = "ABC" },
    new MyDataItem { Id = 1, Value = "BCD" },
    new MyDataItem { Id = 1, Value = "CDE" },
    new MyDataItem { Id = 1, Value = "DEF" },
};

// an anonymous method to define reused HTML/server code
Action<MyDataItem> displayData = delegate(MyDataItem item)
{
    %><span class="my-data-class" title="This is my data!"><%= item.Value %></span><%   
};
%><div><%

// use the displayData delegate to render a table       
%><table><%
foreach (MyDataItem item in data)
{
    %><tr><td><% displayData(item); %></td></tr><%
}   
%></table><%

// use the displayData delegate to render a set of divs
foreach (MyDataItem item in data)
{
    %><div><% displayData(item);%></div><%
}   
%></div><%

The above example renders the following HTML (formatted for clarity):

<div>
  <table>
    <tr>
      <td>
        <span class="my-data-class" title="This is my data!">
        ABC</span>
      </td>
    </tr>
    <tr>
      <td>
        <span class="my-data-class" title="This is my data!">
        BCD</span>
      </td>
    </tr>
    <tr>
      <td>
        <span class="my-data-class" title="This is my data!">
        CDE</span>
      </td>
    </tr>
    <tr>
      <td>
        <span class="my-data-class" title="This is my data!">
        DEF</span>
      </td>
    </tr>
  </table>
  <div>
    <span class="my-data-class" title="This is my data!">ABC</span>
  </div>
  <div>
    <span class="my-data-class" title="This is my data!">BCD</span>
  </div>
  <div>
    <span class="my-data-class" title="This is my data!">CDE</span>
  </div>
  <div>
    <span class="my-data-class" title="This is my data!">DEF</span>
  </div>
</div>
Dr. Wily's Apprentice