2012-06-21 19 views
5

Przychodzę do asp.net MVC 4 z tła w Railsach i mam problemy z ustaleniem, jak sobie radzić z modelami zagnieżdżonymi.ASP.NET MVC 4 - Zagnieżdżone modele - Jak skonfigurować odpowiednie skojarzenia?

Używam Entity Framework 4.3 z podejściem CodeFirst.

Aplikacja jest dość prosta i ma zestaw model - który ma wiele franchising. I ma model franczyzy - który należy do zestawów.

Klasy POCO zostały utworzone wraz z odpowiednimi właściwościami nawigacyjnymi, a następnie zarchiwizowałem kontrolery widokami, a następnie wygenerowałem bazę danych.

Oto klas:

Set

namespace FranchiseManagerTest.Models 
    { 
     public class Set 
     {   
      [Key] 
      public int SetID { get; set; } 
      public string SetName { get; set; } 
      public string MainAddress { get; set; } 
      public string TimeZone { get; set; }  
      public virtual ICollection<Franchise> Franchises { get; set; } 
     } 
    } 

Franchise

namespace FranchiseManagerTest.Models 
{ 
    public class Franchise 
    { 
     [Key] 
     public int FranchiseID { get; set; }   
     public int SetID { get; set; } 
     public string FranchiseName { get; set; } 
     public string FranchiseNumber { get; set; }  

     public virtual Set Set { get; set; } 

    } 
} 

Potem stworzył kilka testowych Zestawy franczyzowych oraz franchising.

Oto główny widok:

enter image description here

Projekt wymaga, aby wszystkie Franczyzy związane z zestawu są widoczne w odpowiedni zestaw. Ponadto, muszę mieć możliwość dodania Franczyzy do zestawu, gdy jestem w szczegółach zestawu.

stworzyłem zrzut ekranu, aby zilustrować jak to wygląda po kliknięciu „szczegółów” na głównym widoku:

enter image description here

New Franchise przycisk jest tworzony z actionlink, który wygląda tak:

@Html.ActionLink("New Franchise", "Create", "Franchise", null, new { @class = "btn btn-large btn-primary" }) 

to prowadzi mnie do Franchise Utwórz stronę, która wygląda tak:

enter image description here

Problem, jak widać, jest to, że rozwijana, które powinny zawierać zbiór powiązanych model nie jest wstępnie wypełniona - zamiast muszę kliknij listę rozwijaną i wybierz ponownie ustawić, że ja już jestem . w

rozwijana jest są wypełniane - ale przez wszystkich istniejących zestawów - zamiast zestawu, że jestem w środku.

Oto rozwijane po kliknięciu na nim:

enter image description here

wnętrza Franchise Tworzenie View, to co, że rozwijana, a jej etykietka wyglądać następująco:

 <div class="editor-label"> 
      @Html.LabelFor(model => model.SetID, "Set") 
     </div> 
     <div class="editor-field"> 
      @Html.DropDownList("SetID", String.Empty) 
      @Html.ValidationMessageFor(model => model.SetID) 
     </div> 

Oto, co próbowałem:


starałem się przekazać w SetID wartość do widoku za pomocą actionlink:

@Html.ActionLink("New Franchise", "Create", "Franchise", Model.SetID, new { @class = "btn btn-large btn-primary" }) 

Potem próbował zmienić atrybut String.Empty z widoku Utwórz do tego:

<div class="editor-label"> 
     @Html.LabelFor(model => model.SetID, "Set") 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("SetID", Model.SetID) 
     @Html.ValidationMessageFor(model => model.SetID) 
    </div> 

Jednak to nie zadziałało i wygenerowało błąd Nieprawidłowy błąd.

Oto możliwy trop

Kiedy odwiedzam Utwórz Franchise Widok z powiązanym Zestaw że jestem, oto co URL wygląda (lub inny problem?):

enter image description here

Przypuszczam, że jeśli związki pomiędzy Ustaw i Franchise były prawidłowe, a kiedy poszedłem dodać Franchise w zestawie, że adres URL będzie loo k to:

localhost:52987/Set/1/Franchise/Create 

Czy to złe założenie - czy można to zrobić w .NET MVC?

Każda rada tutaj jest bardzo doceniana!


edytuje


Oto trasy w moim pliku Global.asax czy jest to pomocne:

public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

      routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 

      routes.MapRoute(
       name: "Default", 
       url: "{controller}/{action}/{id}", 
       defaults: new { controller = "Set", action = "Index", id = UrlParameter.Optional } 
      ); 
     } 

zgodnie z wnioskiem - są tu zarówno GET i POST Utwórz metody kontrolera franszyzy:

// 
    // GET: /Franchise/Create 

    public ActionResult Create() 
    { 
     ViewBag.SetID = new SelectList(db.Sets, "SetID", "SetName"); 
     return View(); 
    } 

    // 
    // POST: /Franchise/Create 

    [HttpPost] 
    public ActionResult Create(Franchise franchise) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Franchises.Add(franchise); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     ViewBag.SetID = new SelectList(db.Sets, "SetID", "SetName", franchise.SetID); 
     return View(franchise); 
    } 

Po prostu daj mi znać, jeśli będzie pomocny kod.

+0

Jak wygląda twoja metoda FranchiseController.Create? – StriplingWarrior

+0

Hey Stripling - Dodałem kod kontrolera do sekcji Edycja mojego OP. To może być coś ze sterownikiem - po prostu nie wiem co. Próbowałem wstawiania parametru SetID do metody GET Create, ale bez powodzenia. Znowu - jestem pewien, że robię to źle. Usunąłem parametr i tak wygląda teraz. – PhillipKregg

+1

Musisz zmienić metodę Create tak, jak sugeruje justinb138. Musi przyjąć parametr 'SetID', aby ten, który został przekazany z linku, mógł zostać użyty jako wartość domyślna w rozwijanym menu. (Możesz nawet chcieć użyć ukrytego wejścia dla tej wartości zamiast menu rozwijanego, chyba że oczekujesz, że ludzie zmienią Franczyzę). – StriplingWarrior

Odpowiedz

3

jestem trochę mylić, co szukasz zrobić, ale chciałbym zaproponować kilka zmian:

by to zmienić:

<div class="editor-label"> 
    @Html.LabelFor(model => model.SetID, "Set") 
</div> 
<div class="editor-field"> 
    @Html.DropDownList("SetID", Model.SetID) 
    @Html.ValidationMessageFor(model => model.SetID) 
</div> 

do tego:

<div class="editor-label"> 
    @Html.LabelFor(model => model.SetID, "Set") 
</div> 
<div class="editor-field"> 
    @Html.DropDownListFor(model => model.SetID, (SelectList)ViewBag.FranchiseSets) 
    @Html.ValidationMessageFor(model => model.SetID) 
</div> 

Jeśli przechodzą w SetID wartości do Tworzenie ActionMethod i przypisać go, powinien dostać pas sed do widoku. Wygląda na to, że nie wypełniasz DropDownList, więc nie ma opcji na liście wyboru do wybrania.

public ActionResult Create(int SetID) 
{ 
    ViewBag.FranchiseSets = new SelectList(...); 
    var franchise = new Franchise { SetID = SetID }; 
    return View(franchise); 
} 
+0

Dzięki za pomoc. Jest to w zasadzie prosta aplikacja CRUD. Działania CRUD muszą być wykonywane na elementach potomnych, gdy znajdują się wewnątrz elementu nadrzędnego. Lista wyboru w widoku Utwórz franczyzę jest wypełniana przez wszystkie istniejące zestawy franszyzy. Problem polega na tym, że tworzę nową Franczyzę w Zestawie - tak, że Zestaw powinien już być pokazany w menu, bez konieczności klikania przez użytkownika listy rozwijanej i ponownego wyboru Zestawu, w którym już są. Czy to ma sens? – PhillipKregg

+0

+1, wspaniała odpowiedź! – StriplingWarrior

+0

Świetnie - wypróbowałem to i wydaje się, że teraz działa. Dzięki za pomoc! – PhillipKregg

1

Nie wiadomo dokładnie, w jaki sposób działania i trasy są ustawione, ale można spróbować to:

@Html.ActionLink("New Franchise", "Create", "Franchise", new{Model.SetID}, new { @class = "btn btn-large btn-primary" }) 

Tworząc obiekt z właściwością SetID, MVC będzie wiedział, że parametr ma być o nazwie "SetID".

PS - czy mogę zaproponować zmianę nazwy Set na (FranchiseSet lub FranchiseGroup itd.), Aby uniknąć kolizji nazw? Setis one of the most ambiguous and common words w języku angielskim.

+0

Dzięki za komentarze - właśnie próbowałem używać nowego {Model.SetId}, ale to niestety nie zadziałało. Opublikuję trasy w moim pliku Global.asax, jeśli chcesz - ale są to standardowe, które są tworzone przez framework. Właściwie to na początku ustawiłem Set na FranchiseSet - ale po utworzeniu bazy danych utworzono by FranchiseSet_ID zamiast FranchiseSetID. Nigdy nie mogłem uzyskać skojarzeń, dopóki nie zmienię nazwy. Mogę spróbować użyć "Franchiseset" zamiast tego. – PhillipKregg

+0

@PhillipKregg: Odnośnie nazwy bazy danych: lepiej będzie nazwać ją 'FranchiseSetId' zamiast' FranchiseSetID'. Struktura prawdopodobnie uważa, że ​​musi dodać podkreślenie, aby odróżnić wielkie litery lub coś podobnego. – StriplingWarrior

Powiązane problemy