Please dont say: why do you use DataTable?
There's nothing wrong in using DataTable. DataTables have been around since the early ages of .NET and it is completely understandable that there is still lots of existing code that relies on them. But that's not a reason why those DataTables should traverse the frontiers from the controller to the view. A controller should always pass a view model to the view. So let's start by defining this view model, shall we:
public class MyViewModel
{
public int? SelectedCustomerId { get; set; }
public IEnumerable<SelectListItem> Customers { get; set; }
public int? SelectedJobId { get; set; }
public IEnumerable<SelectListItem> Jobs { get; set; }
public IEnumerable<string> Columns { get; set; }
public IEnumerable<object> Values { get; set; }
}
We shall also define a view model for the request in order to avoid the ugly parsing that you are currently performing:
public class RequestViewModel
{
public string SubmitButton { get; set; }
public int Customers { get; set; }
public int Jobs { get; set; }
}
Now, how do we hide this DataTable
? We could write an extension method which will convert it to a dynamic object:
public static class DataTableExtensions
{
private sealed class Row : DynamicObject
{
private readonly DataRow _row;
public Row(DataRow row)
{
_row = row;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var value = _row.Table.Columns.Contains(binder.Name);
result = value ? _row[binder.Name] : null;
return value;
}
}
public static IEnumerable<dynamic> AsDynamicEnumerable(this DataTable table)
{
return table.AsEnumerable().Select(row => new Row(row));
}
}
So far so good. The last peace of the puzzle is in the controller action where we shall create our view model:
[HttpPost]
public ActionResult Index(RequestViewModel request)
{
int id = request.Customers;
int scheduleId = request.Jobs;
DataTable dt = JobOperation.GetJobsBySchedulerIdAndCustomerId(scheduleId, id);
// Now let's build the view model for the result:
var model = new MyViewModel();
model.Columns = dt.Columns.Cast<DataColumn>().Select(x => x.ColumnName);
model.Values = dt.AsDynamicEnumerable();
model.Customers = new SelectList(CustomerOperation.GetCustomers().Items, "Id", "Name");
model.Jobs = new SelectList(JobOperation.GetCustomersAssemblyList().Items, "scheduleId", "name");
return View(model);
}
and now we could of course have a strongly typed view:
<%
var grid = new WebGrid(Model.Values);
var columns = Model.Columns.Select(x => grid.Column(x));
%>
<%= grid.GetHtml(columns: columns) %>
// and then we could have dropdowns and other stuff
<%= Html.DropDownListFor(x => x.SelectedCustomerId, Model.Customers, "-- customer --") %>
<%= Html.DropDownListFor(x => x.SelectedJobId, Model.Jobs, "-- job --") %>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…