How to Present a DataTable in an MVC3 Razor view
DataTables are weakly typed. I hate weak typing.
Here's an alternative approach: using view models, strongly typed views and display templates. So start by defining a view model which will represent the information you are willing to display:
public class MyViewModel
{
public IEnumerable<ColumnViewModel> Columns { get; set; }
public IEnumerable<RowViewModel> Rows { get; set; }
}
public class ColumnViewModel
{
public string Name { get; set; }
}
public class RowViewModel
{
public IEnumerable<CellValueViewModel> Values { get; set; }
}
public class CellValueViewModel
{
public string Value { get; set; }
}
then you could have a controller action which will populate this view model. If you already have some service layers that spits DataTables, you could map those tables to the aforementioned view model. For the purpose of this demo let's hardcode:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Columns = new[]
{
new ColumnViewModel { Name = "column1" },
new ColumnViewModel { Name = "column2" },
new ColumnViewModel { Name = "column3" },
},
Rows = new[]
{
new RowViewModel
{
Values = new[]
{
new CellValueViewModel { Value = "1x1" },
new CellValueViewModel { Value = "1x2" },
new CellValueViewModel { Value = "1x3" },
}
},
new RowViewModel
{
Values = new[]
{
new CellValueViewModel { Value = "2x1" },
new CellValueViewModel { Value = "2x2" },
new CellValueViewModel { Value = "2x3" },
}
},
new RowViewModel
{
Values = new[]
{
new CellValueViewModel { Value = "3x1" },
new CellValueViewModel { Value = "3x2" },
new CellValueViewModel { Value = "3x3" },
}
}
}
};
return View(model);
}
}
and the last part is the view (~/Views/Home/Index.cshtml
):
@model MyViewModel
<table>
<thead>
<tr>
@Html.DisplayFor(x => x.Columns)
</tr>
</thead>
<tbody>
@Html.DisplayFor(x => x.Rows)
</tbody>
</table>
and our display templates:
~/Views/Home/DisplayTemplates/ColumnViewModel.cshtml
:
@model ColumnViewModel
<th>
@Html.DisplayFor(x => x.Name)
</th>
~/Views/Home/DisplayTemplates/RowViewModel.cshtml
:
@model RowViewModel
<tr>
@Html.DisplayFor(x => x.Values)
</tr>
~/Views/Home/DisplayTemplates/CellValueViewModel.cshtml
:
@model CellValueViewModel
<td>
@Html.DisplayFor(x => x.Value)
</td>
And that's pretty much all. As you can see we have written exactly zero loops in our views and we ended up with a nice <table>
structure representing an Excel Worksheet.
ProfK
I am a software developer in Johannesburg, South Africa. I specialise in C# and ASP.NET, with SQL Server. I have, in some way or another, been involved in software development for about eighteen years, but always learning something new. At the moment that is WPF and MVVM.
Updated on June 26, 2022Comments
-
ProfK almost 2 years
I have a reliable and tested import method between an .xls spreadsheet[1] that returns a
DataTable
. I've located this in my service layer, not data as only the workbook gets persisted as an uploaded file, but now I'm wondering where and how to produce an HTML representation of thisDataTable
. I would prefer to avoid two loops in my view. I have a variable number of columns in theDataTable
.[1] Using an OleDb interface. I know it's archaic but it works.