1

I have MVC application with a model like this :

public class ListOfMyModel
{
    public List<MyModel> MyModels { get; set; }
    public Guid MyID { get; set; }
}

public class MyModel
{
    // Some code like :
    public string MyString { get; set; }
}

And my post method in my controller is like this :

[HttpPost]
public ActionResult EditMe(ListOfModel myList)
{
    try
    {
        if (ModelState.IsValid)
        {
            List<MyModel> myModels = myList.MyModels;

            foreach (MyModel model in myModels)
                // Some code

            return RedirectToAction("Index");
        }
    catch
    {
        // Some code
        return View(myList)

    }
    return View(myList);
}

And my view : ( I use Kendo UI ) ( P.S : Some code has been stripped away and replaced by comment code )

@model MyApplication.Web.Models.ListOfMyModel
@{
ViewBag.Title = MyTitle;
Layout = "~/Views/Shared/_MyLayout.cshtml";
 }

<div class="span1"></div>
<div class="span8">
    <div id="list-wrapper">
        <div class="k-content">
            <form id="form" class="form-horizontal well span8 offset2" method="post" action="@Url.Action("EditMe")">

            <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/jquery-1.9.1.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/kendo/2013.1.514/kendo.web.min.js")"></script>
            <script src="@Url.Content("~/Scripts/kendo/2013.1.514/kendo.aspnetmvc.min.js")"></script>

             <div class="offset2 span2">
                <fieldset>
                    <legend> My title </legend>
                    <p>Some code :</p>
                    @Html.HiddenFor(m => m.MyID)
                    @for (int i = 0; i < Model.MyModels.Count; i++)
                    {
                    // Some code
                    <div class="control-group">
                        <label class="control-label">MyText : </label>
                        <div class="controls">
                        @(Html.Kendo().DropDownListFor(c =>                 Model.MyModels[i].MyString)
                                        .DataTextField("Text")
                                        .DataValueField("Value")
                                        .DataSource(dataSource => dataSource 
                                            .Read(read => read.Action("GetSomeThings", "MyController"))
                                        )
                                        .Value(Model.MyModels[i].MyString)
                                    )
                         </div> 
                     </div>
                     }
                     <div class="form-actions"> 
                        <button type="submit" class="btn btn-primary">Validate</button>
                    </div> 
                 </fieldset>
              </div>
           </form>
        </div>
    </div>
 </div>

But the problem is that when I push the submit button in my view, the method of my controller is called with all the data expected ( saw in Chrome ) but in this method, all of the model is null : The ID and the list... I don't known where the problem is ?

Thank you all for reading and trying to understand this, if you want more informations please tell me.

Frédéric Guégan
  • 109
  • 1
  • 2
  • 7

1 Answers1

0

The MyId should be correctly received with your existing code.

The model binder can only match the value of inputs whose name have a matching property in the form. I.e. if you have an input like this <input name='bikes' ...> then your model should have a property Bikes so that the model binder can transfer the value from the input to the property. In your case you're creating input with dynamic names that doesn't have a matching property name. (NOTE: thei referes to the model you're using as the action parameter).

The farthest you can go is giving a series of input elements the same name, i.e. several elements like <input name='categories' ...> and receive it in an array parameter like string[] categories or a model which has a property like string[] Categories {get;set;}

In short, you have to redesign your model and view. If you used a List<string> instead of a List<MyModel>, and the view had a fixed name for the dropdow lists, like DropDownListFor(c => Model.MyModels, then the model binder would fill the MyModels property with the list of selected strings in each drop down list.

Hint: you can use a model for the View and receive a different model (or series of parameters) in the Action. In this way you can send more information to render the View, and receive a post with the essential data to process the user input.

See my answer to this question for alternatives. It explains something similar to this question.

Community
  • 1
  • 1
JotaBe
  • 38,030
  • 8
  • 98
  • 117