Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I post a list of items in MVC

I have a simple form with a list of items in it and I'd like to post them to the controller but funny thing is I just cant. Everything else goes through properly except the list. I checked the ajax call in firebug and the post values are there like this:

Answers[0].IsMissing    False
Answers[0].Text Ja
Answers[0].Value    0
Answers[1].IsMissing    False
Answers[1].Text Nein
Answers[1].Value    1
Id  1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d
Name    Ja/Nein

I have an AnwserScheme class with the following properties:

public string Name { get; set; }
public bool IsMissing { get; set; }
public List<AnswerDisplayItem> Answers { get; set; }

public AnswerScheme()
{
    Answers = new List<AnswerDisplayItem>();
}

I have this view code:

@for (int i = 0; i < Model.Answers.Count; i++) {
    <tr>
        <td>
            @Html.HiddenFor(model => Model.Answers[i].IsMissing)
            @Html.TextBoxFor(model => Model.Answers[i].Value, 
                             new { @class = "inputValue" })
        </td>
        <td>
            @Html.TextBoxFor(model => Model.Answers[i].Text, 
                             new { @class = "inputAnswer" })
        </td>
        <td>
            <span class="span-delete" 
                  data-answer-scheme-id="@Model.Id" 
                  data-answer-id="@Model.Answers[i].Id" >x</span>
        </td>
    </tr>
}

I have this piece of ajax code that is responsible for posting:

$.ajax({
    url: "/AnswerScheme/AddAnswer",
    type: "post",
    data: $("#formAnswerScheme").serialize(),
    success: function (data) {
                 console.log(data);
                 $("#divAnswerSchemeContainer").html(data);
             }
});

I have an add answer action in my controller:

[HttpPost]
public PartialViewResult AddAnswer(AnswerScheme answerScheme)
{
    ...some logic comes here
}

So in the end the controller recieves the model, but only the simple properties, not the list. Any help would be greatly appreciated! cheers.

like image 489
JahManCan Avatar asked May 01 '13 16:05

JahManCan


3 Answers

I wish I could see more of your classes and code, because you don't have something set up right.

I recreated something from what you did provide, which works. I created an MVC 3 project for this sample.

Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>

    <body>
        @RenderBody()
    </body>
</html>

Views/Shared/_Partial.cshtml

@model RazorListTest.Models.AnswerScheme 

<table>
@for (int i = 0; i < Model.Answers.Count; i++) {
    <tr>
        <td>
            @Html.HiddenFor(model => Model.Answers[i].IsMissing)
            @Html.TextBoxFor(model => Model.Answers[i].Value, new { @class = "inputValue" })
        </td>
        <td>
            @Html.TextBoxFor(model => Model.Answers[i].Text, new { @class = "inputAnswer" })
        </td>
        <td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
    </tr>
}
</table>

Models/AnswerDisplayItem.cs

using System.Collections.Generic;

namespace RazorListTest.Models
{
    public class AnswerDisplayItem
    {
        public bool IsMissing { get; set; }
        public string Text { get; set; }
        public string Value { get; set; }
        public string Id { get; set; }
    }

    public class AnswerScheme
    {
        public List<AnswerDisplayItem> Answers { get; set; }
        public string Id { get; set; }

        public AnswerScheme()
        {
            Answers = new List<AnswerDisplayItem>();
        }
    }
}

Home/Index.cshtml

@model RazorListTest.Models.AnswerScheme

    @using (Html.BeginForm(null, null, FormMethod.Get, new { name="formAnswerScheme", id = "formAnswerScheme"}))
    {
        {Html.RenderPartial("_Partial");}

        <div>
            <input type="button" value="Click me" id="btnClick"/>
        </div>

        <div id="divAnswerSchemeContainer">

        </div>
    }

<script type="text/javascript">
    $("#btnClick").click(function () {

        $.ajax({
            url: 'Home/AddAnswer',
            type: 'POST',
            dataType: 'json',
            data: $("#formAnswerScheme").serialize(),
            success: function (data) {
                console.log(data);
                $("#divAnswerSchemeContainer").html(data);
            },
            error: function (xhr, textStatus, exceptionThrown) { alert(JSON.parse(xhr.responseText)); }
        });
    });
</script>

Controllers/HomeController.cs

using System.Collections.Generic;
using System.Web.Mvc;
using RazorListTest.Models;

namespace RazorListTest.Controllers
{
    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            AnswerScheme a = new AnswerScheme();

            a.Id = "1cd14b08-ce3b-4671-8cf8-1bcf69f12b2d";

            List<AnswerDisplayItem> adi = new List<AnswerDisplayItem>();
            AnswerDisplayItem a1 = new AnswerDisplayItem();
            a1.IsMissing = false;
            a1.Text = "Ja";
            a1.Value = "0";
            a1.Id = "1234";
            AnswerDisplayItem a2 = new AnswerDisplayItem();
            a2.IsMissing = false;
            a2.Text = "Nein";
            a2.Value = "1";
            a2.Id = "5678";
            adi.Add(a1);
            adi.Add(a2);
            a.Answers = adi;
            return View(a);
        }

        [HttpPost]
        public JsonResult AddAnswer(AnswerScheme answerScheme)
        {
            return Json("the list is in the Model.");
        }
    }
}
like image 177
TheGeekYouNeed Avatar answered Nov 01 '22 09:11

TheGeekYouNeed


Its almost identical what TheGeekYouNeed posted, but i guess something is just missing. I have no clue what that could be.

AnswerScheme view:

@using System.Web.Mvc.Html
@using MetaDataPortal.Models
@model AnswerScheme

 @{
ViewBag.Title =  @Model.IsMissing ? "Missing" : "AnswerScheme";
Layout = "~/Views/Shared/_Layout.cshtml";
}

@section CssContent{
<link href="../../Content/CSS/AnswerScheme.css" rel="stylesheet" />
}


 @using (Html.BeginForm("Save", "AnswerScheme", FormMethod.Post, new { id = "formAnswerScheme" })) {

<div id="divAnswerSchemeContainer">
    @{Html.RenderPartial("_AnswerScheme", Model);}
</div>
<input type="button" class="clear inputButton" id="buttonAddCode" value="Add @(Model.IsMissing ? "Missing" : "Answer")" />

<input type="submit" value="Save" />
}

 @section Javascript{
<script type="text/javascript">
    $(function () {
        $("#buttonAddCode").click(function () {
            $.ajax({
                url: "/AnswerScheme/AddAnswer",
                type: "post",
                async: false,
                data: $("#formAnswerScheme").serialize(),
                success: function (data) {
                    console.log(data);
                    $("#divAnswerSchemeContainer").html(data);
                }
            });
            return false;
        });
    });

</script>
<script type="text/javascript" src="~/Content/JavaScript/AnswerScheme.js"></script>
 }

_AnswerScheme partialview

        @model MetaDataPortal.Models.AnswerScheme

        @Html.HiddenFor(model => model.Id, new { Id = "AnswerSchemeId" })
            <ul class="ulGeneralForm">
                <li>
                    @Html.LabelFor(model => model.Name, "Name", new { @class = "labelGeneral" })
                    @Html.TextBoxFor(model => model.Name, Model.Name, new { @class = "textBoxGeneral" })
                </li>
                <li>
                    @Html.Label(@Model.IsMissing ? "Missings" : "Answers", new { @class = "labelGeneral" })
                    <table class="textualData links downloadList">
                        <thead>
                            <tr>
                                <th>Value</th>
                                <th> @(Model.IsMissing ? "Missing" : "Answer")</th>
                                <th></th>
                            </tr>
                        </thead>
                        <tbody id="tbodyCodeContainer">
                            @for (int i = 0; i < Model.Answers.Count; i++) {
                                <tr>
                                    <td>
                                        @Html.HiddenFor(model => Model.Answers[i].IsMissing)
                                        @Html.TextBoxFor(model => Model.Answers[i].Value, new { @class = "inputValue" })
                                    </td>
                                    <td>
                                        @Html.TextBoxFor(model => Model.Answers[i].Text, new { @class = "inputAnswer" })
                                    </td>
                                    <td><span class="span-delete" data-answer-scheme-id="@Model.Id" data-answer-id="@Model.Answers[i].Id" >x</span></td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </li>
            </ul>

AnswerScheme.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;

 using Opit.Rogatus.DomainObjects;


 namespace MetaDataPortal.Models
 {
public class AnswerScheme : BaseModel
{
    public string Name { get; set; }
    public bool IsMissing { get; set; }

    public List<AnswerDisplayItem> Answers { get; set; }

    public AnswerScheme()
    {
        Answers = new List<AnswerDisplayItem>();
    }

    public AnswerScheme(CodeList codeList, bool isMissing) : this()
    {
        Id = codeList.Id;
        Name = codeList.Name;
        IsMissing = isMissing;
        foreach (Code code in codeList.Codes.Where(code => code.Category.IsMissing == isMissing))
        {
            Answers.Add(new AnswerDisplayItem(code));
        }
    }
      }
    }

AnswerDisplayItem.cs:

    using System;

    using Opit.Rogatus.DomainObjects;


    namespace MetaDataPortal.Models
    {
        public class AnswerDisplayItem
        {
            public Guid Id { get; private set; }
            public short Value { get; private set; }
            public string Text { get; private set; }
            public Guid AnswerSchemeId { get; set; }
            public bool IsMissing { get; private set; }

            public AnswerDisplayItem()
            {
            }

            public AnswerDisplayItem(Code code)
            {
                Id = code.Id;
                Value = code.Value;
                Text = code.Category.Name;
                IsMissing = code.Category.IsMissing;
                if (code.CodeList == null) return;

                AnswerSchemeId = code.CodeList.Id;
            }
        }
    }

And controller is pretty much the same.

like image 1
JahManCan Avatar answered Nov 01 '22 07:11

JahManCan


You can do like this create model

 public class ApplicationInfo
{
        public List<ApplicationAccessRoles> ApplAccessRoleInfo { get; set; }
    }

 public class ApplicationAccessRoles
{
    public int app_access_role_key { get; set; }
    public int app_key { get; set; }
    public string access_role { get; set; }
    public bool inactive { get; set; }
}

put it in view

       <div class="step-pane" id="step3">
                    <div class="form-horizontal" style="vertical-align:central;margin-left:150px">
                        <table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table">
                            <tr class="dataheader">
                                <td class="width5">
                                    &nbsp;
                                    @Html.HiddenFor(m => m.app_access_role_key)
                                </td>
                                <td class="width200">
                                    Access Roles Name
                                </td>
                                <td class="width10">
                                    Inactive
                                </td>

                            </tr>
                            @if (Model.ApplAccessRoleInfo.Count!= 0)
                            {
                                var chk = Model.ApplAccessRoleInfo.Count;
                                for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
                                {
                                    <tr class="exp_col_header top_border_nil">
                                       @if ((chk - 1) == a)
                                        { 
                                        <td><a href="#" class="gridexpand" rel="1"></a></td>
                                        }
                                        else
                                        {
                                            <td></td>
                                        }
                                        <td>
                                            @Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
                                            @Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
                                        </td>
                                        <td>
                                            @Html.CheckBox("ApplTeamAccessInfo[" + a.ToString() + "].inactive", false, new { @class = "check-box"})
                                        </td>
                                    </tr>
                                }
                            }
                            else
                                {
                                    <tr class="exp_col_header top_border_nil">
                                    <td>
                                        <a href="#" class="gridexpand" rel="1"></a>
                                    </td>
                                    <td>
                                        @*@Html.EditorFor(model => model.access_role)*@
                                        @*@Html.EditorFor(m => m.ApplAccessRoleInfo[0].access_role)*@
                                        @Html.EditorFor(model=>model.access_role)
                                    </td>
                                    <td>
                                        @Html.CheckBoxFor(model => model.inactive)
                                    </td>
                                    </tr>

                            }
                        </table>

                    </div>
                </div>

In Controller

  var main = (from a in db.mas_app_access_roles
                    where a.app_key == AppInfo.app_key
                    select new  ApplicationAccessRoles
                    {
                        app_access_role_key = a.app_access_role_key,
                        access_role = a.access_role,
                        inactive = a.inactive,
                    }).ToList();
        access = main;
        AppInfo.ApplAccessRoleInfo = access;
        ViewBag.check = access;

        return View(AppInfo);
like image 1
Aravind Kb Avatar answered Nov 01 '22 08:11

Aravind Kb