2013-07-12 8 views
5

Mam klasę o nazwie CategoryModel, której jedną z właściwości jest lista obiektów tego samego typu. Tak więc CategoryModel.Categories jest typu List<CategoryModel>.Edytor MVC Dla wiązania modelu dla wielu formularzy edycji na jednej stronie

Na stronie indeksu kategorii wyświetlam edytor dla każdej kategorii, dzięki czemu użytkownik może zmienić dowolne nazwy kategorii bez konieczności przechodzenia na dedykowaną stronę, aby to zrobić. Tak:

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

A szablon edytor CategoryModel wygląda następująco:

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

Mam problem jest to, że złożenie formularza nie wiąże się poprawnie do działania CategoryControllerEdit:

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

Jeśli sprawdzę nazwy w ukrytych polach i polach tekstowych, zostaną one oznaczone na podstawie ich pozycji w bieżącej mapie ory (np. Categories[0].Name). Jeśli jednak utworzę dedykowany widok edycji, zostaną one po prostu nazwane zgodnie z nazwą pola (np. Name).

Próbowałem zmienić kontroler przyjąć listę kategorii:

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

To działa, jeśli przedstawi bardzo pierwszej kategorii, ale żaden z innych (w tych przypadkach Categories jest null).

Próbowałem również zmienia sposób mogę wyświetlać moje EditorFor, wykonując w ten sposób:

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

która zmienia nazwy pól być takie same dla każdej kategorii (np wszystkie nazwy kategorii są nazywane cat.Name), które wierzymy, że jest to krok we właściwym kierunku.

Jak mogę poprawnie powiązać mój kontroler? Zdaję sobie sprawę, że mogę przesłać całą kategorię nadrzędną, a następnie zapisać każdą podkategorię, ale wydaje się to bardzo nieefektywnym sposobem na przesłanie pojedynczej zmiany.

Odpowiedz

6

odkryłem jak to zrobić. Jest przeciążenia dla Html.EditorFor które pozwala określić właściwość htmlFieldName (trzeci parametr w poniższym przykładzie):

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

Czyni to wszystko z nazwami pól, bez przedrostka i pozwala mi przedstawić każdą pojedynczą kategorię powodzeniem .

+1

Zrobiłem to, ale nadal otrzymuję [0] i [1] po nazwach pól, jak sobie z tym poradziłeś? – Dennis

+1

Nie dostałem problemu, który opisałeś. Jeśli użyłeś @ Html.EditorFor (model => model.Categories, null, "") zamiast powyższej pętli, otrzymasz przed nazwami pól [0] i [1], ponieważ przekazujesz tablicę do metoda EditorFor zamiast pojedynczego modelu. – Maloric

0

Twoja akcja edycji akceptuje kategorię CategoryModel, dlatego konieczne jest zresetowanie prefiksu modelu w celu poprawnego powiązania. Do tego trzeba stworzyć własną metodę rozszerzenia do HtmlHelper tak:

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

a następnie użyć go wewnątrz szablonu edytora:

@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

Niestety ma to ten sam problem co pętla foreach - nazwy pól to Kategorie [0] .Nazwa, Kategorie [1] .Nazwa itp., A Model kategorii nie wiąże się z działaniem Edycja. – Maloric

+0

Przykro mi z powodu niezrozumienia twojego pytania. Edytowałem swoją odpowiedź. –

Powiązane problemy