1

I'm trying to dynamically create a form with different types of fields. Then simply pass the user inputted data back to the controller and bind back to my model. I'm using a custom editor template for each control and was hoping it would bind properly in the controller. However, the property is NULL each time so I cannot retrieve the input values.

Model

public class ReceiptModel : ClassBase
{
    public int ReceiptId { get; set; }
    public List<CustomControlModel> CustomControlList { get; set; }
}

public class CustomControlModel 
{
    public string CustomControlName { get; set; }
    public CustomControlType CustomControlType { get; set; }
}

View

@foreach (CustomControlModel ccm in @Model.CustomControlList)
{
    if (!string.IsNullOrEmpty(ccm.PropertyName))
    {
        @Html.EditorFor(model => ccm, "CustomControlModel")
    }
}

Custom Template

@Html.HiddenFor(model => model.CustomControlId)


<label>@Model.LabelCaption</label>

@switch (@Model.CustomControlType)
{

case CustomControlType.TEXTBOX:
                    if (@Model.ReadOnly)
                    {

                        @Html.TextBoxFor(model => model.CustomControlId, new { @readonly = "readonly", @Value = @Model.Value })
                    }
                    else
                    {

        <input id="@Model.CustomControlName" name="@Model.CustomControlName" type="text" value="@Model.Value" />
}

Any help would be much appreciated. Thanks in advance.

btorkelson
  • 89
  • 2
  • 10
  • It simply needs to be `@Html.EditorFor(m => m.CustomControlList)` - no `foreach` loop assuming you have located the `EditorTemplate` in the `/Views/Shared/EditorTemplates` folder (or the `/Views/yourControllerName/EditorTemplates` folder). But its a bit unclear what `if (!string.IsNullOrEmpty(ccm.PropertyName))` is for - you model does not have a property named `PropertyName` –  Jan 08 '16 at 23:17
  • Take a look at this simple project: https://github.com/SirwanAfifi/SimpleFormGenerator – Sirwan Afifi Jan 09 '16 at 08:23
  • Thanks for the quick response. This works well to get my controls on the page, but the inputted values are not being set with the model binder. When the user submits the form, can't I simply reference the values in the model or is there a trick to get the new values? – btorkelson Jan 09 '16 at 15:14
  • If your POST method has a parameter `ReceiptModel model` then it will be correctly bound (including the collection) when you submit. If your having problems, then you need to post more code. –  Jan 10 '16 at 09:14
  • @StephenMuecke I assume the problem is in my custom editor template. Code added above. – btorkelson Jan 10 '16 at 15:36
  • Yes it is :) I assume you have multiple `switch` statements but if you look at the first one its trying to bind the `Value` property to the `CustomControlId` property (which makes no sense and would not wrk any way because you have a hidden input for `CustomControlId` which will be bound first so your `@Html.TextBoxFor()` will be ignored) and then if the `ReadOnly` property is false, you generate a input with a `nmae` attribute that has no relationship to your model and your indexers are now non-consecutive (so binding would fail anyway) –  Jan 10 '16 at 22:05
  • @StephenMuecke Thank you so much for your responses. You have been very helpful. – btorkelson Jan 11 '16 at 05:03
  • Possible duplicate of [MVC ViewModel Binding Construction vs. Flattening](https://stackoverflow.com/questions/34997672/mvc-viewmodel-binding-construction-vs-flattening) – Steve Harris Mar 02 '18 at 14:39

1 Answers1

1

Don't use foreach. It does not result in the correct property names in the rendered html and so the properties will not be picked up by the model binder. Use a for loop instead:

@for (int i = p; I < @Model.CustomControlList.Count; i++)
{
    if (!string.IsNullOrEmpty(Model.CustomControlList[i].PropertyName))
    {
        @Html.EditorFor(model => model.CustomControlList[i], "CustomControlModel")
    }
}
Steve Harris
  • 5,014
  • 1
  • 10
  • 25