2013-07-12 19 views
5

Ho una classe denominata CategoryModel, una delle cui proprietà è un elenco di oggetti dello stesso tipo. Quindi CategoryModel.Categories è di tipo List<CategoryModel>.MVC Editor Per il binding del modello per più moduli di modifica su una pagina

Nella pagina dell'indice delle categorie, visualizzo un editor per ogni categoria in modo che l'utente possa modificare qualsiasi nome di categoria senza dover accedere a una pagina dedicata per farlo. In questo modo:

<ul id="categories> 
    @Html.EditorFor(model => model.Categories) 
</ul> 

E l'editor di modelli per CategoryModel assomiglia a questo:

<li class="folder"> 
    @using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) { 
     @Html.ValidationSummary(true) 
     @Html.HiddenFor(model => model.Key) 
     @Html.HiddenFor(model => model.ParentKey) 
     @Html.HiddenFor(model => model.Sequence) 
     @Html.HiddenFor(model => model.IncludeDeleted) 

     @Html.TextBoxFor(model => model.Name, null, new { @class = "catName" }) 
     @Html.ValidationMessageFor(model => model.Name) 

     <input type="submit" value="Save" class="icon save" /> 
    } 
</li> 

Il problema che ho è che l'invio del modulo non si lega correttamente alla Edit azione del CategoryController:

[HttpPost] 
public ActionResult Edit(CategoryModel category) 
{ 
    // At this point all properties in category are null 
} 

Se controllo i nomi sui campi nascosti e sulle caselle di testo, sono etichettati in base alla loro posizione nella categoria corrente ory (ad es. Categories[0].Name). Se creo una vista di modifica dedicata, tuttavia, vengono semplicemente denominati in base al nome del campo (ad esempio Name).

Ho provato a cambiare il controller di accettare un elenco di categorie:

[HttpPost] 
public ActionResult Edit(List<CategoryModel> categories) 
{ 
    var category = categories.First(); 
} 

questo funziona se presento la prima categoria, ma nessuno degli altri (in quei casi Categories IS NULL).

Ho anche provato a cambiare come mi espongo il mio EditorFor, in questo modo:

<ul id="categories> 
    @foreach (var cat in Model.Categories) 
    { 
     @Html.EditorFor(model => cat); 
    } 
</ul> 

che cambia i nomi dei campi di essere la stessa per ciascuna categoria (ad esempio, tutti i nomi delle categorie sono chiamati cat.Name), che ho credo sia un passo nella giusta direzione.

Quindi, come si collega in modo corretto al controller? Mi rendo conto che potrei inviare l'intera categoria genitore e quindi salvare ogni sottocategoria, ma questo sembra un modo molto inefficiente per inviare una singola modifica.

risposta

6

ho scoperto come fare questo. C'è un sovraccarico per Html.EditorFor che consente di specificare la proprietà htmlFieldName (il terzo parametro nell'esempio qui sotto):

@foreach (var cat in Model.Categories) 
{ 
    @Html.EditorFor(model => cat, null, ""); 
} 

Questo rende tutti i nomi dei campi senza alcun prefisso e mi permette di presentare alcuna singola categoria con successo .

+1

Ho fatto questo, ma ricevo ancora [0] e [1] dopo i nomi dei campi, come hai affrontato questo? – Dennis

+1

Non ho avuto il problema che hai descritto. Se hai usato @ Html.EditorFor (model => model.Categories, null, "") invece del ciclo precedente, dovresti ottenere [0] e [1] prima dei nomi dei campi, tuttavia, perché stai passando un array a il metodo EditorFor invece di un singolo modello. – Maloric

0

L'azione Modifica accetta categoria Categoria di modello, quindi è necessario reimpostare il prefisso del modello per l'associazione destra. Per questo è necessario creare il proprio metodo di estensione per HtmlHelper come questo:

public class BeginHtmlScope : IDisposable 
    { 
     private readonly TemplateInfo templateInfo; 
     private readonly string previousHtmlFieldPrefix; 

     public BeginHtmlScope(TemplateInfo templateInfo, string htmlFieldPrefix) 
     { 
      this.templateInfo = templateInfo; 

      previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix; 
      templateInfo.HtmlFieldPrefix = htmlFieldPrefix; 
     } 

     public void Dispose() 
     { 
      templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix; 

     } 
    } 
    public static class MyHtmlExtensions 
    { 
     public static IDisposable BeginHtmlScope(this HtmlHelper html, string htmlFieldPrefix) 
     { 
      return new BeginHtmlScope(html.ViewData.TemplateInfo, htmlFieldPrefix); 
     } 
    } 

E poi utilizzarlo all'interno del vostro editor di modelli:

@using (Html.BeginHtmlScope("")) 
{ 
    <li class="folder"> 
    @using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) { 
     @Html.ValidationSummary(true) 
     @Html.HiddenFor(model => model.Key) 
     @Html.HiddenFor(model => model.ParentKey) 
     @Html.HiddenFor(model => model.Sequence) 
     @Html.HiddenFor(model => model.IncludeDeleted) 

     @Html.TextBoxFor(model => model.Name, null, new { @class = "catName" }) 
     @Html.ValidationMessageFor(model => model.Name) 

     <input type="submit" value="Save" class="icon save" /> 
    } 
</li> 

} 
+0

Sfortunatamente questo ha lo stesso problema del ciclo foreach - i nomi dei campi sono Categorie [0]. Nome, Categorie [1]. Nome ecc. E CategoryModel non si associa all'azione Modifica. – Maloric

+0

Mi dispiace per aver frainteso la tua domanda. Ho modificato la mia risposta. –

Problemi correlati