2015-03-09 4 views
8

Nella mia applicazione MVC 4, ho un cliente che può avere più siti e può iscriversi a più pacchetti di servizi. Una versione breve del mio modello di vista assomiglia sottoElenco di oggetti non vincolanti per il modello sul post back in asp.net mvc 4

public class SubscriptionModel 
{   
    public int MemberId { get; set; } 
    public List<SitePackage> SitePackges { get; set; } 
    public SubscriptionModel() 
    { 
     SitePackges=new List<SitePackage>(); 
    } 
} 

public class SitePackage 
{ 
    public int SiteId { get; set; } 
    public List<PackageDisplayItem> LstPackageDisplayItems { get; set; } 
    public SitePackage() 
    { 
     LstPackageDisplayItems=new List<PackageDisplayItem>(); 

    } 
} 

public class PackageDisplayItem 
{ 
    public int PackageId { get; set; } 

    [Display(Name = "Package")] 
    public string Name { get; set; }   

    [DataType(DataType.Date)] 
    [Display(Name = "Start Date")] 
    public DateTime? StartDate { get; set; } 

} 

Nel mio regolatore I compilare il modello e poi passare alla vista del modello per il rendering

@using (@Html.BeginForm("CalculateCost", "HelpDesk", FormMethod.Post, new { @class = "form", id = "PackageSubscription", name = "PackageSubscription" })) 
{ 
@Html.HiddenFor(x=>x.MemberId) 

<table class="table"> 
    @foreach (var site in Model.SitePackges) 
    { 
    <input name="SiteId" id="SiteId" type="hidden" [email protected]() /> 
      <tr><td class="col-sm-3">@site.SiteId</td></tr> 
      <tr> 
       <th class="col-sm-3"> 
        Name 
       </th> 

       <th class="col-sm-2"> 
        Start Date 
       </th> 
      </tr> 
      @Html.Partial("_Packages",site.LstPackageDisplayItems)    

     } 

La mia visione parziale è come

@model List<PackageDisplayItem> 

@for (int i = 0; i < Model.Count; i++) 
{ 
    @Html.HiddenFor(x => x[i].PackageId) 
    <tr id="@Model[i].PackageId"> 
     <td> 
      @Html.DisplayFor(x => x[i].Name) 
     </td> 

     <td> 
      @Html.TextBoxFor(x => x[i].StartDate, "{0:d MMM yyyy}", new { @class = "jquery_datepicker form-control", autocomplete = "off" }) 
     </td> 
    </tr> 

} 

Ogni cosa rende bene ma sul modulo di post il modello di legatura non è vincolante SitePackges lista e il suo conteggio è sempre 0. Il mio controller ha le seguenti firme.

[HttpPost] 
    public ActionResult CalculateCost(SubscriptionModel subscriptionModel) 
    { 
     var receivedModel = subscriptionModel;   
    } 

Non sono sicuro se il modello che ho disegnato è l'approccio migliore per gestire questo requisito (Il requisito è quello di mostrare un unico sito e appena sotto di essa mostra il pacchetti e poi 2 ° sito e pacchetti, e così via). Sembra che i controlli abbiano generato indici univoci.

Jquery Messaggio

function SubmitForm() { 
console.log($("#PackageSubscription").serialize()); 
$.ajax({ 
    url: '/HelpDesk/CalculateCost', 
    cache: false, 
    dataType: 'json', 
    data: $("#PackageSubscription").serialize(), 
    type: 'POST', 
    success: function (data) { 
    } 

}); 

}

mi apprezzeranno alcun aiuto. grazie

+2

uso ciclo for con indicizzazione –

risposta

9

È implementazione attuale sta rendendo ingressi che assomigliano:

<input ... name="[0].Name" .../> 
<input ... name="[1].Name" .../> 

ma allo scopo di impegnare per te modello che avrebbe bisogno di simile a questa:

<input ... name="SitePackges[0].LstPackageDisplayItems[0].Name" .../> 
<input ... name="SitePackges[0].LstPackageDisplayItems[1].Name" .../> 
<input ... name="SitePackges[1].LstPackageDisplayItems[0].Name" .../> 
<input ... name="SitePackges[1].LstPackageDisplayItems[1].Name" .../> 

A: È necessario rendere i controlli in nidificato for loop

for(int i = 0; i < Model.SitePackges.Count; i++) 
{ 
    @Html.HiddenFor(m => m.SitePackges[i].SiteId) 
    for(int j = 0; j < Model.SitePackges[i].LstPackageDisplayItems.Count; j++) 
    { 
    @Html.TextBoxFor(m => m.SitePackges[i].LstPackageDisplayItems[j].Name) 
    } 
} 

B: o utilizzare personalizzato EditorTemplates per voi i tipi di modello

Vista/shared/EditorTemplates/SitePackage.cshtml

@model SitePackage 
@Html.HiddenFor(m => m.SiteId) 
@Html.EditorFor(m => m.LstPackageDisplayItems) 

Vista/Shared/EditorTemplates/PackageDisplayItem.cshtml

@model PackageDisplayItem 
@Html.TextBoxFor(m => m.Name) 

e nella vista principale

@model SubscriptionModel 
@using (@Html.BeginForm()) 
{ 
    @Html.HiddenFor(m => m.MemberId) 
    @Html.EditorFor(m => m.SitePackges) 
    <input type="submit" /> 
} 
+1

perfetto. Grazie mille!! hai ripulito il mio concetto. – rumi

+0

L'associazione funziona perfettamente con il modulo di invio, ma quando sto cercando di inviare il modulo tramite jquery e serializzare il modulo, il collegamento di nuovo non funziona. Ho aggiunto il codice di richiamo jQuery nella domanda. Il log sulla console mostra tutti i valori del modulo che sono necessari per eseguire il binding con l'indicizzazione corretta. Qualche idea? – rumi

+1

Non ricordo la corretta configurazione delle opzioni di ajax (avremo bisogno di controllare in seguito) ma se si usa solo '$ .post ('@ Url.Action (" CalculateCost "," HelpDesk ")', $ ('form') .serialize(), function (data) {...}); 'dovrebbe funzionare bene (jquery' .post' funziona tutto per te) –

0

Ho scoperto che è necessario avere l'ID per l'elemento nel pannello padre contenente.

int pos = Model.Products.Count - 1; 
for (int j = 0, a = Model.Products.Count; j < a; j++) { 
    // I exclude the last one because the users is adding it 
    // and will be displayed in another section. else causes problems 
    if (j != pos) { 
    <div> 
     @Html.HiddenFor(m => m.Products[j].Id) 

     <span> 
      @Html.DisplayTextFor(m => m.Products[j].Description) 
      @Html.HiddenFor(m => m.Products[j].Description) 
     </span> 
     <span> 
      @Html.DisplayTextFor(m => m.Products[j].Style) 
      @Html.HiddenFor(m => m.Products[j].Style) 
     </span> 
    </div> 
    } 
} 

questo no lavoro sotto

for (int j = 0, a = Model.Products.Count; j < a; j++) { 
    if (j != pos) { 
    <div> 
     @Html.HiddenFor(m => m.Products[j].Id) 
     @Html.HiddenFor(m => m.Products[j].Description) 
     @Html.HiddenFor(m => m.Products[j].Style) 
    </div> 
    } 
} 

o questa

for (int j = 0, a = Model.Products.Count; j < a; j++) { 
    if (j != pos) { 
    <div> 
     <span> 
      @Html.HiddenFor(m => m.Products[j].Id) 
     </span> 

     <span> 
      @Html.DisplayTextFor(m => m.Products[j].Description) 
      @Html.HiddenFor(m => m.Products[j].Description) 
     </span> 
     <span> 
      @Html.DisplayTextFor(m => m.Products[j].Style) 
      @Html.HiddenFor(m => m.Products[j].Style) 
     </span> 
    </div> 
    } 
}