My first ASP MVC task involved building a dynamic form, and it isn't straight forward Basically you can't use the built in helpers or validation because they expect strongly typed objects My view basically loops through the input fields, checks the DataType (bool, int, string, datetime etc) and builds an editor directly for that type You also have to do all your validation manually, decorating the types with attributes to do this doesn't work, see my question if(ModelState. IsValid) doesn't work with FormsCollection. What to use instead?
Razor View logic (we use DevExpress MVC extensions, but you get the drift) The form object and it's Fields collection are our bespoke objects that describe how the form should look (the page gathers criteria for searches, which is why you'll see criteria and search type names in the code) table id="criteriaTable"> @foreach (var field in form. Fields) { @if (field. IsVisible) { @Html.DevExpress().
Label(s => s. Text = field. Caption).GetHtml() @if (field.
Type == typeof(bool)) { @Html. CheckBox(s => { s. Checked = field.
IsBoolSet; s. Name = field. Name; s.
ClientEnabled =!field. IsReadonly; }).GetHtml() } else if (field. Type == typeof(DateTime)) { Html.DevExpress().
DateEdit(s => { s. Name = field. Name; s.
ClientEnabled =!field. IsReadonly; if (!string. IsNullOrEmpty(field.
Value)) { DateTime dateValue; if (DateTime. TryParse(field. Value, out dateValue)) s.
Date = dateValue; } }).GetHtml(); } else if (field.ListValues. Count > 0) { Html.DevExpress(). ListBox(s => { s.Name = field.
Name; s. ClientVisible = field. IsVisible; s.
ClientEnabled =!field. IsReadonly; s.Properties. SelectionMode = DevExpress.Web.ASPxEditors.
ListEditSelectionMode. CheckColumn; s.Properties. TextField = "Name"; s.Properties.
ValueField = "Value"; s.Properties. ValueType = typeof(string); //s.Properties. EnableClientSideAPI = true; foreach (var item in field.
ListValues) { s.Properties.Items. Add(item.Name, item. Value); } //s.Properties.
ClientSideEvents. SelectedIndexChanged = "MultiSelectListChanged"; s.Properties. ClientSideEvents.
Init = "MultiSelectListInit"; }).GetHtml(); } else { //Html. TextBox(field. Name, field.
Value) Html.DevExpress(). TextBox(s => { s. Name = field.
Name; s. Text = field. Value; }).GetHtml(); } @Html.
ValidationMessage(field.Name) @Html.DevExpress(). CheckBox(s => { s. Checked = field.
IncludeInSearch; s. Name = "use_" + field. Name; s.
ClientEnabled = (!field. IsMandatory); }).GetHtml() } } Fields) { var value = (formCollectionfield. Name?
"").Trim() If there are any validation errors I can specify control level validation by adding a ModelError directly to the model e. G ModelState. AddModelError(field.
Name, "This is a mandatory field") and I return the View if there are validation errors Hope this helps.
My first ASP MVC task involved building a dynamic form, and it isn't straight forward. Basically you can't use the built in helpers or validation because they expect strongly typed objects. My view basically loops through the input fields, checks the DataType (bool, int, string, datetime etc) and builds an editor directly for that type.
You also have to do all your validation manually, decorating the types with attributes to do this doesn't work, see my question if(ModelState. IsValid) doesn't work with FormsCollection. What to use instead?
Razor View logic (we use DevExpress MVC extensions, but you get the drift) The form object and it's Fields collection are our bespoke objects that describe how the form should look (the page gathers criteria for searches, which is why you'll see criteria and search type names in the code). @foreach (var field in form. Fields) { @if (field.
IsVisible) { @Html.DevExpress(). Label(s => s. Text = field.
Caption).GetHtml() @if (field. Type == typeof(bool)) { @Html. CheckBox(s => { s.
Checked = field. IsBoolSet; s. Name = field.Name; s.
ClientEnabled =!field. IsReadonly; }).GetHtml() } else if (field. Type == typeof(DateTime)) { Html.DevExpress().
DateEdit(s => { s. Name = field.Name; s. ClientEnabled =!field.
IsReadonly; if (!string. IsNullOrEmpty(field. Value)) { DateTime dateValue; if (DateTime.
TryParse(field. Value, out dateValue)) s. Date = dateValue; } }).GetHtml(); } else if (field.ListValues.
Count > 0) { Html.DevExpress(). ListBox(s => { s. Name = field.
Name; s. ClientVisible = field. IsVisible; s.
ClientEnabled =!field. IsReadonly; s.Properties. SelectionMode = DevExpress.Web.ASPxEditors.
ListEditSelectionMode. CheckColumn; s.Properties. TextField = "Name"; s.Properties.
ValueField = "Value"; s.Properties. ValueType = typeof(string); //s.Properties. EnableClientSideAPI = true; foreach (var item in field.
ListValues) { s.Properties.Items. Add(item. Name, item.
Value); } //s.Properties. ClientSideEvents. SelectedIndexChanged = "MultiSelectListChanged"; s.Properties.
ClientSideEvents. Init = "MultiSelectListInit"; }).GetHtml(); } else { //Html. TextBox(field.
Name, field. Value) Html.DevExpress(). TextBox(s => { s.
Name = field.Name; s. Text = field. Value; }).GetHtml(); } @Html.
ValidationMessage(field. Name) @Html.DevExpress(). CheckBox(s => { s.
Checked = field. IncludeInSearch; s. Name = "use_" + field.Name; s.
ClientEnabled = (!field. IsMandatory); }).GetHtml() } } The Controller action accepts a Forms Collection. I loop through the formsCollection looking for the control names I specified in the view.
HttpPost public ActionResult QueryCriteria(FormCollection formCollection) { var isValid = true; foreach (var field in form. Fields) { var value = (formCollectionfield.Name? "").Trim(); ... If there are any validation errors I can specify control level validation by adding a ModelError directly to the model e.g. ModelState.
AddModelError(field. Name, "This is a mandatory field"); and I return the View if there are validation errors. Hope this helps.
This solution was my first thought too but I hoped there is a way to re-use MVC editor-templating like Html.Editor(), Html.EditorFor(), Display(), DisplayFor(), etc. But as you wrote they may not fit in the use-case where one needs to build a dynamic form where no strictly typed data is around. – Marc Sep 14 at 7:12 I like the tip with the FormCollection instead of using Request.Form. Tha's an 'accept` :) – Marc Sep 14 at 11:57 Thanks :) – Binary Worrier Sep 14 at 12:36.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.