Reputation: 601
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.
Upvotes: 19
Views: 69792
Reputation: 7539
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.");
}
}
}
Upvotes: 34
Reputation: 35
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">
@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);
Upvotes: 1
Reputation: 10248
Try changing either the controller parameter name to "answers" or the property name to AnswerScheme and if the partial controller in your post is supposed to be recieving the list then change the type to:
List<AnswerScheme> answers
Upvotes: 0
Reputation: 601
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.
Upvotes: 1
Reputation: 307
The problem is with the name/id attribute of your text boxes and other input controls. You can use editor templates to make things seamless and reusable.. Another example here.
But if you still want to loop through things, your loop has to look something in these examples here or here.
Upvotes: 0