I am currently working on a ASP.NET MVC 3 project in which I need to build a report builder. The report model has to be generic and just be “implemented” for any report. The report has certain criteria that should be met: these are the “Filter Values”, which is in the form op select lists, and Include additional information (yes-no-option), that can be any child entity that has to be included in the report, and finally the layout of the report which is a enum. Here is the code i have so far for the report builder model:
public class ReportBuilderModel
{
public IList<FilterModel> FilterCriteria { get; set; }
public Dictionary<string, bool> AdditionalInformation { get; set; }
public ReportType ReportType { get; set; }
public String ReportName { get; set; }
public ReportBuilderModel()
{
}
public ReportBuilderModel(string reportName)
{
FilterCriteria = new List<FilterModel>();
AdditionalInformation = new Dictionary<string, bool>();
ReportName = reportName;
}
public void AddFilterCriteria(String fieldName, Object lookupObject)
{
FilterModel model = new FilterModel()
{
FieldName = fieldName,
LookupObject = lookupObject
};
FilterCriteria.Add(model);
}
public void AddAdditionalInformation(String fieldName, bool defaultValue)
{
AdditionalInformation.Add(fieldName, defaultValue);
}
}
public class FilterModel
{
public String FieldName { get; set; }
public Object LookupObject { get; set; }
}
public enum ReportType
{
Detail,
List,
Form,
Transaction
}
The view associated with this is as follows:
@model EduTOOL.Models.ReportBuilderModel
@{
ViewBag.Title = "Report Builder";
}
@Html.LoadPartial(EduTOOL.Controllers.PartialViewName._EditorForLibraries)
@using (Html.BeginForm())
{
<h2>
Build Report for @Model.ReportName</h2>
<div style="float: left; width: 35%; height: 20%;">
<fieldset>
<legend>Filter Criteria</legend>
<table>
@foreach (var filter in Model.FilterCriteria)
{
String displayText = "Select a " + filter.FieldName;
<tr>
<td>@Html.DisplayFor(label => displayText)
</td>
</tr>
<tr>
<td>@Html.EditorFor(editor => filter.LookupObject)
</td>
</tr>
}
</table>
</fieldset>
</div>
<div style="float: left; width: 35%; height: 20%;">
<fieldset>
<legend>Options</legend>
<table>
@foreach (var includeInfo in Model.AdditionalInformation)
{
String displayText = "Include " + includeInfo.Key + " information?";
<tr>
<td>@Html.DisplayFor(label => displayText)
</td>
</tr>
<tr>
<td>
@Html.EditorFor(includeValue => includeInfo.Value)
</td>
</tr>
}
</table>
</fieldset>
<br />
<br />
</div>
<div style="float: right; width: 30%; height: 20%;">
<fieldset>
<legend>Report Type</legend>
<br />
<table>
@foreach (var reportType in Enum.GetValues(Model.ReportType.GetType()))
{
<tr>
<td>
@Html.DisplayFor(displayText => reportType)
</td>
<td>
@Html.RadioButtonFor(radio => reportType, reportType.ToString())
</td>
</tr>
}
</table>
</fieldset>
<br />
<br />
</div>
<br />
<input class="button cyan" value="Generate Report" type="submit" />
}
These are all called by these action controller methods:
public ActionResult TestReport()
{
ReportBuilderModel model = new ReportBuilderModel("Distributor Contact List");
model.AddFilterCriteria("Distributor", DistributorController.GetDefaultAutoComplete());
model.AddFilterCriteria("Status", ActiveStatus.Active);
model.AddAdditionalInformation("Contact", true);
model.AddAdditionalInformation("History", true);
return View(model);
}
[HttpPost]
public ActionResult TestReport(ReportBuilderModel model)
{
return View();
}
The trouble is no binding occurs between the HTTPGET and HTTPPOST for the model, and I dont know exaclty how to bind the models? Also i would like to know if this is a good way to build a report wizzard? The values that are chosen in the report builder wizzard will be handled by the controller that makes use of the builder. The idea here is to get a list of selected criteria for the three options and generate the report using that criteria.
I am not allowed to use 3rd party controls. Any help will be appreciated. Thank you so much!
because you are binding to a list of FilterCriteria it doesn’t know how to bind it because it needs the name property set. Basically you have a bunch of input elements on the screen but you havn’t given them a name so that it can identify which on to bind to on the post.
Here is a good article on model binding. I would suggest binding something simple at first, like a text box. The move up to list and a list of objects inside another object. Model Binding