Note that there are some explanatory texts on larger screens.

plurals
  1. POBinding a nested collection in MVC3
    primarykey
    data
    text
    <p>I have a ViewModel which contains a list of polymorphic objects.</p> <pre><code>public class InputParameters { public InputParameters() { InputPrompts = new List&lt;IInputPrompt&gt;(); } public string Name { get; set; } public string Path { get; set; } public IList&lt;IInputPrompt&gt; InputPrompts { get; set; } } </code></pre> <p>Which in turn look this:</p> <pre><code>public interface IInputPrompt { string Name { get; set; } bool IsHidden { get; set; } bool IsRequired { get; set; } dynamic Value { get; set; } } public class TextPrompt : IInputPrompt { public string Name { get; set; } public bool IsHidden { get; set; } public bool IsRequired { get; set; } public dynamic Value { get; set; } } public class MultiSelectPrompt : IInputPrompt { public string Name { get; set; } public bool IsHidden { get; set; } public bool IsRequired { get; set; } public dynamic Value { get; set; } public MultiSelectList Values { get { return new MultiSelectList(((IDictionary&lt;int, string&gt;)Value).ToList(), "Key", "Value"); } } } </code></pre> <p>There is a Editor View Template for each of the derived types, the views look this this:</p> <pre><code>@model OptionListModelBinding.Models.InputParameters @{ ViewBag.Title = "Index"; } &lt;h2&gt;Index&lt;/h2&gt; @using (Html.BeginForm()) { &lt;fieldset&gt; &lt;legend&gt;&lt;strong&gt;@Model.Name&lt;/strong&gt;&lt;/legend&gt; &lt;div&gt;&lt;em&gt;@Model.Path&lt;/em&gt;&lt;/div&gt; &lt;div&gt;@Html.EditorFor(p =&gt; p.InputPrompts)&lt;/div&gt; &lt;div&gt;&lt;input type="submit" /&gt;&lt;/div&gt; &lt;/fieldset&gt; } // editor template @model OptionListModelBinding.Models.InputParameters @{ ViewBag.Title = "Index"; } &lt;h2&gt;Index&lt;/h2&gt; @using (Html.BeginForm()) { &lt;fieldset&gt; &lt;legend&gt;&lt;strong&gt;@Model.Name&lt;/strong&gt;&lt;/legend&gt; &lt;div&gt;&lt;em&gt;@Model.Path&lt;/em&gt;&lt;/div&gt; &lt;div&gt;@Html.EditorFor(p =&gt; p.InputPrompts)&lt;/div&gt; &lt;div&gt;&lt;input type="submit" /&gt;&lt;/div&gt; &lt;/fieldset&gt; } // editor template @model OptionListModelBinding.Models.MultiSelectPrompt @{ ViewBag.Title = "MultiSelectPrompt"; } &lt;h2&gt;MultiSelectPrompt&lt;/h2&gt; &lt;div&gt;&lt;strong&gt;@Model.Name&lt;/strong&gt;&lt;/div&gt; &lt;div&gt;&lt;em&gt;@Html.ListBox(Model.Name, Model.Values)&lt;/em&gt;&lt;/div&gt; </code></pre> <p>This all renders nicely:<img src="https://i.stack.imgur.com/eRs7O.png" alt="Screen Capture"></p> <p>The question is this:</p> <p>How do I bind this back to the model? I have a custom model binder: (excuse the hacked up nature of this code).</p> <pre><code> public class InputParameterModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } // iterate over the form fields foreach (string item in controllerContext.HttpContext.Request.Form.AllKeys) { // this is where the problem is ... I cannot use the generic here. var dog = FromPostedData&lt;string&gt;(bindingContext, item); } InputParameters userInput = new InputParameters(); return userInput; } // Dino Esposito code private T FromPostedData&lt;T&gt;(ModelBindingContext context, string id) { if (String.IsNullOrEmpty(id)) return default(T); var key = String.Format("{0}.{1}", context.ModelName, id); var result = context.ValueProvider.GetValue(key); if (result == null &amp;&amp; context.FallbackToEmptyPrefix) { result = context.ValueProvider.GetValue(id); if (result == null) return default(T); } context.ModelState.SetModelValue(id, result); T valueToReturn = default(T); try { valueToReturn = (T)result.ConvertTo(typeof(T)); } catch { } return valueToReturn; } } </code></pre> <p><strong>EDIT</strong> Did i mention that the items in the list are determined at runtime?</p> <p><strong>EDIT</strong> This is the front end of a report generating tool. The backend service provides a list of available reports and the parameters needed to run each one. None of this is known at compile time and the report definitions can even change with the web portal needing to be recompiled.</p> <p>I can have a variable number and type of input parameters.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload