What I have is a form with multiple inputs that I want to use to query database for some results. Form has some default values and it all works, however I have problem submitting it to itself.
The returned error is "No paramaterless constructor defined for this object" and it is caused by SelectList object.
I have tried this solution and made psUserType private with getter and setter and intialized it as empty list, but then my dropDown menu had no values on start. Not sure why GetUserTypes hadn't filled them.
What am I doing wrong here? How does one have both preselected values and also send the same model with user-selected values, while also displaying results on the same page?
Does it make sense to use the same model for all 3 actions: 1. display form and inputs with default values 2. post selected values during submit 3. return results and selected values? I've read this solution also but not sure how to use 2 or 3 separate models here.
Any help is appreciated. Thanks in advance.
Model
public class SearchDownloadsModel
{
public SelectList psUserType { get; private set; } //causes problem on submit
public string psText { get; set; }
public MultiSelectList psColumns { get; private set; }
public IEnumerable<ResultsRowModel> psResults { get; set; }
public SearchDownloadsModel()
{
this.psUserType = GetUserTypes();
this.psColumns = GetColumns();
this.psResults = new List<ResultsRowModel>(); //empty by default
}
public SelectList GetUserTypes()
{
List<SelectListItem> items = new List<SelectListItem>()
{
new SelectListItem { Value="user", Text="Single User" },
new SelectListItem { Value="group", Text="User group" },
...
};
return new SelectList(items, "Value", "Text");
}
public MultiSelectList GetColumns()
{
List<SelectListItem> items = new List<SelectListItem>()
{
new SelectListItem { Value = "user", Text="Username" },
new SelectListItem { Value = "file", Text="Filename" },
new SelectListItem { Value = "titl", Text="Title" },
new SelectListItem { Value = "auth", Text="Author" },
...
};
return new MultiSelectList(items, "Value", "Text");
}
}
public class ResultsRowModel
{
public int ID { get; set; }
public string EventTime { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public string UserName { get; set; }
...
}
View
@model Proj.Models.SearchDownloadsModel
@using (Html.BeginForm("Downloads", "Home", FormMethod.Post))
{
@Html.DropDownListFor(x => x.psUserType, Model.psUserType)
@Html.TextBoxFor(x => x.psText)
@Html.ListBoxFor(x => x.psColumnsSelected, Model.psColumns, new { multiple = "multiple" })
<button type="submit" class="btn btn-primary">Search</button>
}
@if (Model.psResults != null && Model.psResults.Any())
{
<table>
<tr>
<th>User</th>
<th>File</th>
</tr>
@foreach (var row in Model.psResults)
{
<tr>
<td>@row.UserName</td>
<td>@row.FileName</td>
</tr>
}
</table>
}
Controller
[HttpGet]
public ActionResult Downloads()
{
SearchDownloadsModel model = new SearchDownloadsModel();
model.psColumnsSelected = new List<string>() { "user", "file" }; //preselected values
return View(model);
}
[HttpPost]
public ActionResult Downloads(SearchDownloadsModel model)
{
model.psResults = queryDatabase(model);
return View(model);
}
private List<ResultsRowModel> queryDatabase(SearchDownloadsModel model)
{
//...
}
EDIT: Added ResultsRowModel under SearchDownloadsModel