2013-05-01 12 views
15

Ho un semplice modulo con un elenco di elementi in esso e mi piacerebbe postarli al controller, ma la cosa divertente è che non posso. Tutto il resto passa correttamente tranne la lista. Ho controllato la chiamata AJAX in Firebug ei valori post-ci sono come questo:Come posso pubblicare un elenco di articoli in MVC

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 

devo una classe AnwserScheme con le seguenti proprietà:

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

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

ho questo codice della vista:

@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> 
} 

ho questo pezzo di codice Ajax che è responsabile per la pubblicazione:

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

Ho un'azione risposta aggiuntivo nel mio controller:

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

Così, alla fine del controllore riceve il modello, ma solo le semplici proprietà, non la lista. Qualsiasi aiuto sarebbe molto apprezzato! Saluti.

+1

È possibile controllare questo articolo per un tutorial su come fare legame alle collezioni modello: http://haacked.com/archive/2008/10/23/model-binding-to-a- list.aspx – Kenneth

+1

Stai utilizzando MVC3 o MVC4? Perché il tuo codice funziona bene in un progetto MVC4 appena creato ... Puoi pubblicare per intero il codice del modulo '# formAnswerScheme'? – nemesv

+0

Si prega di inviare l'intero modello AnswerScheme e l'intero modulo dal BeginForm verso il basso (e includere l'istruzione @model) –

risposta

29

Vorrei poter vedere più classi e codice, perché non hai impostato correttamente qualcosa.

Ho ricreato qualcosa da quello che hai fornito, che funziona. Ho creato un progetto MVC 3 per questo esempio.

Visite/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> 

Visite/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> 

modelli/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(), 
      async: false, 
      success: function (data) { 
       console.log(data); 
       $("#divAnswerSchemeContainer").html(data); 
      }, 
      error: function (xhr, textStatus, exceptionThrown) { alert(JSON.parse(xhr.responseText)); } 
     }); 
    }); 
</script> 

Controller/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."); 
     } 
    } 
} 
+0

Grazie a tutti gli sforzi, l'uomo è davvero completo. btw fondamentalmente ho fatto tutto proprio come hai fatto tu e ancora semplicemente non vuole lavorare. Fastidioso. Im posterò tutti i miei codici, forse c'è un'ambientazione che mi manca o che non so. – JahManCan

+0

In un nuovo progetto MVC4 il tuo codice funziona perfettamente. Ma cosa faccio di sbagliato allora ?! – JahManCan

+0

Non ne ho idea. Inserisco il tuo in un nuovo progetto e funziona anche. Ho creato un codice, una CodeList e una classe di categoria in modo da poter rimanere fedele al tuo codice esatto. Sono perplesso – TheGeekYouNeed

0

Il problema è con l'attributo nome/id delle caselle di testo e altri controlli di input. È possibile utilizzare editor templates per rendere le cose senza soluzione di continuità e riutilizzabili .. Un altro esempio here.

Ma se si desidera ancora eseguire il loop delle cose, il loop deve cercare qualcosa in questi esempi here o here.

+0

No, non ci sono problemi con la sua denominazione. Sì, dovrebbe usare i modelli di editor, ma la sua denominazione va bene nel modo in cui lo sta facendo. –

0

suoi quasi identici quanto pubblicato TheGeekYouNeed, ma credo che qualcosa è solo manca. Non ho idea di cosa potrebbe essere.

AnswerScheme vista:

@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; 
      } 
     } 
    } 

e il controllore è praticamente la stessa.

+0

Puoi pubblicare le tue classi Code, CodeList e Category? – TheGeekYouNeed

0

Provare a cambiare sia il nome del parametro di controllo di "risposte" o il nome della proprietà per AnswerScheme e se il controller parziale tuo post dovrebbe essere riceve la lista quindi modificare il tipo di:

List<AnswerScheme> answers 
0

È può fare come questo modello di creare

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; } 
} 

mise in vista

 <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> 

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); 
Problemi correlati