2011-01-28 18 views
15

To może być bardzo proste, ale nie mogę go rozwiązać samodzielnie. Stworzyłem prostą db i jednostki modal, który wygląda takdropdown w edytorze mvc3

enter image description here

próbuję stworzyć Utwórz formularz, który pozwala mi dodać nowy porządek. Mam w sumie 3 tabele, więc próbuję wprowadzić formularz umożliwiający wpisanie daty zamówienia, a także listę rozwijaną, która pozwala mi wybrać produkt z tabeli produktów:

Chcę być w stanie utworzyć widok Dodaj lub Edytuj, który pozwala mi wstawić OrderDate do OrderTable, a także wstawić OrderID i wybrany ProductID do OrderProduct.

Jakie kroki należy tutaj wykonać?

I stworzyli OrderController i zaznaczyć „Dodaj Actions” i nie dodaje się Utwórz widok, który wygląda jak ten

@model Test.OrderProduct 

@{ 
    ViewBag.Title = "Create2"; 
} 

    <h2>Create2</h2> 

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

@using (Html.BeginForm()) { 
    @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>OrderProduct</legend> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.OrderID) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.OrderID) 
      @Html.ValidationMessageFor(model => model.OrderID) 
     </div> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.ProductID) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.ProductID) 
      @Html.ValidationMessageFor(model => model.ProductID) 
     </div> 

     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 
} 

<div> 
    @Html.ActionLink("Back to List", "Index") 
</div> 

Stwarza to pogląd, który zawiera pole tekstowe zarówno OrderID i IDProduktu jednak żadnej daty.

Mój kontroler CreatePost hasnt zmieniono

[HttpPost] 
    public ActionResult Create(FormCollection collection) 
    { 
     try 
     { 
      var data = collection; 
      // TODO: Add insert logic here 
      // db.Orders.AddObject(collection); 
      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

Moje pytania są

1.How mogę zamieniać ProductID tekstowe być rozwijana, która jest wypełniana od Produktu 2.How mogę dostać dane z kolekcji FormCollection? Myślałem o foreach jednak nie wiem jak uzyskać silnie wpisaną nazwę

Każda pomoc dla początkującego byłaby bardzo pomocna.

Dziękujemy!

+0

To zabawne, że to jest dokładnie to pytanie, które mam w tej chwili, a jednak nikt tutaj nie odpowiedział. Myślałam, że ci ćpeci z MVC skoczyliby na to w ciągu 2 sekund. –

Odpowiedz

25

Pierwsza rzecz pierwsza, nie wiąże się z jednostką Zamówienie. Nigdy nie łącz z obiektem EF, zawsze spróbuj użyć modelu ViewModel. Ułatwia to życie Viewowi, a to jest celem tutaj.

Więc mam ViewModel tak:

public class CreateOrderViewModel 
{ 
    public int OrderId { get; set; } 
    public DateTime OrderDate { get; set; } 
    public int SelectedProductId { get; set; } 
    public IEnumerable<SelectListItem> Products { get; set; } 
} 

to jest to teraz.

Powrót do widoku, który w swoim działaniu [HttpGet] Kontroler:

[HttpGet] 
public ActionResult Create() 
{ 
    var model = new CreateOrderViewModel 
    { 
     Products = db.Products 
        .ToList() // this will fire a query, basically SELECT * FROM Products 
        .Select(x => new SelectListItem 
        { 
         Text = x.ProductName, 
         Value = x.ProductId 
        }); 
    }; 

    return View(model); 
} 

Następnie do renderowania na Listę Produktów: (podstawowy tryb HTML wyłączone)

@model WebApplication.Models.CreateOrderViewModel 

@Html.DropDownListFor(model => model.SelectedProductId, Model.Products) 

Jedyne co mi się nie robić wiedzieć, jak to zrobić, to powiązać pole DateTime. Zgaduję, że potrzebujesz metody rozszerzenia (HTML Helper), która renderuje selektora dat lub coś takiego. W przypadku tego widoku (tworzenie nowego zamówienia) domyślnie jest to DateTime.Now.

Teraz na działanie [HttpPost] kontrolera:

[HttpPost] 
public ActionResult Create(CreateOrderViewModel model) 
{ 
    try 
    { 
     // TODO: this manual stitching should be replaced with AutoMapper 
     var newOrder = new Order 
     { 
     OrderDate = DateTime.Now, 
     OrderProduct = new OrderProduct 
     { 
      ProductId = SelectedProductId 
     } 
     }; 

     db.Orders.AddObject(newOrder); 
     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     return View(); 
    } 
} 

Teraz Myślę też model EF wymaga pracy.

Dla mnie (w języku angielskim), Produkt może mieć wiele zamówień, a zamówienie może mieć wiele produktów.

Powinno to być wiele-do-wielu. Obecnie jest to 1-1 ze zbędnym połączeniem. Czy wygenerowałeś to z DB? Jeśli tak, twój DB prawdopodobnie potrzebuje pracy.

Trzeba właściwość nawigacyjna nazywa Produkty na zlecenie podmiotu , która odwołuje się do zbierania Produkt, możliwe dzięki niemy dołączyć do stołu przyłączyć się wiele-do-wielu.

Oznacza to również, że nie ma już DropDownList, ale MultiSelectDropDownList.

+0

w powyższej metodzie '[HttpGet]', ciągle pojawia się błąd mówiący mi, że nie mogę niejawnie przekonwertować int na napis dla 'value = x.id' bit! Dodałem 'ToString()' ale potem dostaję ten błąd: Błąd Nie można niejawnie przekonwertować typu "System.Collections.Generic.IEnumerable " na "System.Collections.Generic.IEnumerable '. Istnieje wyraźna konwersja (czy brakuje Ci obsady?) – Ben

+0

@Ben - najprawdopodobniej brakujące odwołanie do użycia – RPM1984

+0

@ RPM1984 Czy mógłbyś wyjaśnić, dlaczego nie powiążesz bezpośrednio z EF? Jaki jest powód? Jeśli spojrzeć na to, wygląda to prościej, adnotacje są szanowane i wszystkie. – Anderson

1

Zmagałem się z tym przez ostatni dzień. Podzielę się moją ograniczoną wiedzą w nadziei, że pomoże to komuś innemu.

Należy pamiętać, że używam singleton z wstępnie wypełnioną listą, aby moja przykładowa aplikacja była mała (brak interakcji EF lub DB).

Aby wyświetlić listę produktów, konieczne będzie posiadanie elementu ViewBag lub ViewData zawierającego listę ProductList. Można to skonfigurować w sterowniku z czymś jak

ViewData["ProductList"] = new SelectList(Models.MVCProduct.Instance.ProductList, "Id", "Name", 1); 

Następnie zaktualizować View to coś podobnego:

<div class="editor-field">@Html.DropDownList("ProductList")</div> 

na stanowisko/Tworzenie/krok aktualizacji trzeba spojrzeć na FormCollection do zdobądź swoje wyniki. Czytanie innych postów brzmi, jakby był tutaj błąd, ale teraz jest naprawiony, więc upewnij się, że masz najnowszy. Dla mojego przykładu mam DropDownList dla produktu, więc wybieram właśnie wybrany Id, a następnie szukam tego Produktu na mojej liście.

[HttpPost] 
    public ActionResult Create(FormCollection form)//Models.MVCOrder newOrder) 
    { 

     MVC.Models.MVCOrder ord = Models.MVCOrder.Instance.CreateBlankOrder(); 
     //Update order with simple types (e.g. Quantity) 
     if (TryUpdateModel<MVC.Models.MVCOrder>(ord, form.ToValueProvider())) 
     { 
      ord.Product = Models.MVCProduct.Instance.ProductList.Find(p => p.Id == int.Parse(form.GetValue("ProductList").AttemptedValue)); 
      ord.Attribute = Models.MVCAttribute.Instance.AttributeList.Find(a => a.Id == int.Parse(form.GetValue("attributeId").AttemptedValue)); 
      UpdateModel(ord); 
      return RedirectToAction("Index"); 
     } 
     else 
     { 
      return View(ord); 
     } 
    } 

Pracowałem tylko nad MVC3 przez ostatnie kilka dni, więc wszelkie rady dotyczące poprawy powyższego byłyby mile widziane.

2

Dzięki Craig. Twoje kilka dni (w momencie wysłania) z MVC rozwiązało moje kilka dni próbując odzyskać wybraną wartość z DropDownListFor.

Nie miałem problemu w widoku Utwórz w uzyskaniu wybranej wartości DDLF, ale widok Edycja był zupełnie inną sprawą - nic, co próbowałem, nie przywróciłoby wybranej wartości w poście. Zauważyłem, że wybrana wartość czaiła się w usiłowanej wartości ModelState, więc Dr.Google odesłał mnie tutaj.

miałem to moim zdaniem

@Html.DropDownList(model => model.ContentKeyID, Model.ContentKeys, Model.ContentKeyName) 

gdzie ContentKeys jest SelectList zaludnionych z DB za pośrednictwem ViewModel i ContentKeyName jest curently wybrana nazwa.

Dziwne jest to, że mam inny DDL w widoku wypełnionym w identyczny sposób. Ten działa. Dlaczego, nie wiem. Jest to drugie DDL w formularzu, ale nie widzę, żeby to miało znaczenie.

Czytałem gdzieś indziej, być może dlatego, że używałem Guida jako Id, ale to nie miało większego znaczenia - zmieniłem na Int32, ale nie sądzę, że musiałem - myślę, że to wyliczenie które nie zgadzają się z DDLF. Nullable również nie mają znaczenia.

Teraz Dodałem kolekcję formularz do mojego postu ActionResult i uzyskać wybraną wartość za pomocą

-widok

@Html.DropDownList("ContentKey", Model.ContentKeys) 

-in kontrolera (post)

contentKeyId = int.Parse(form.GetValue("ContentKey").AttemptedValue); 

wszystko jest w porządku, i mogę przejść do bardziej ekscytujących rzeczy. Dlaczego te najprostsze rzeczy mogą cię tak długo utrzymywać?