2012-03-27 22 views
0

Ich bin verwirrt darüber, wie mein Viewmodel in MVC3 zu aktualisieren. Was ich auf Knopfdruck versuche, suche mein Viewmodel nach einem bestimmten Listenelement. Beispiel:Updating Modell aus der Sicht

BooksViewModel 

public List<Book> Books{get;set;} 

Meiner Ansicht nach, wenn der Benutzer klickt auf eine Schaltfläche ich die Liste in der Ansichtsmodell wie folgt suchen müssen:

Controller 
public void SetContent(int chapterId, int paragraphId) 
{ 
    var paragraph = booksViewModel.Books.Where(b =>b.ChapterId == chapterId).First().Chapter.Paragraphs.Where(p => p.Id == paragraphId).First() 
    model.CurrentParagraph = paragraph; 
} 

Das Problem, das ich habe ist, dass ich die Instanz zugreifen kann nicht des BooksViewModel vom Controller. Wie greife ich auf die Instanz des Ansichtsmodells zu, die die Ansicht verwendet, die bereits über die Daten verfügt, die aus der Datenbank abgerufen wurden? Oder mache ich das alles falsch?

Vielen Dank im Voraus

bearbeiten

Maxime vorgeschlagen an den Controller an den sekundären Anruf in meinem Modell aus der Sicht vorbei

(dh das Modell zu filtern) würde ich das tun, indem Verwenden Sie das Schlüsselwort @Model wie folgt:

Als ich das versuchte, schien es der Ajax Anruf c hoked auf @Model

+0

Ja, das werde ersticken - kann das gesamte Modell auf die URL wie das nicht nur anhängen. Es weiß nicht, wie man das in eine URL-codierte Zeichenfolge übersetzt. – Leniency

Antwort

1

, dass die Bahn und Ansichten staatenlos sind. Sobald die Aktion ausgeführt wurde, ist sie weg (es sei denn, du machst Sessions, aber das ist ein anderes Biest).

Wenn Sie die Liste durchsuchen wollen, nachdem sie an die Ansicht übergeben wurde, in einer anderen Controller-Aktion (brandneue Anfrage, alles aus der vorherigen Anfrage ist weg), dann müssen Sie die Liste neu erstellen.

public MyController 
{ 
    public ActionResult Index() 
    { 
     var books = _service.GetBooks(); 
     return View(new BooksViewModel 
     { 
      Books = books 
     }); 
    } 

    // Once the button is clicked, it routes to this action: 
    [HttpPost] 
    public ActionResult SetSelectedContent(int paragraphId) 
    { 
     // Here you search for the specific paragraph that you want. 
     // Ideally this goes in a service call, but here to illustrate. 
     // The linq query won't materialize every book, but will give an 
     // optimized query that only gives the paragraph that you want. 
     // Depending on your model structure, this will work better. 

     // Paragraph Id's should be unique, yes? so no need for the chapter 
     // then. 
     var paragraph = database.Paragraphs 
      .Single(p => p.paragraphId == paragraphId); 

     // Note the 'Content' here, not View. This will return just the 
     // plain text to be replaced by ajax. 
     return Content(paragraph); 
    } 
} 

Hier ist das Update für das Ajax-Beispiel:

$.ajax({ 
     type: "POST", 
     url: "/Books/SetSelectedContent", 

     // populate the data with whatever the chapter and paragraph id should be. 
     data: { pargraphId: @paragraphId } 
     success: function(result) { 
      // Here you do something with the result. 
      // This would just replace a specific div with the contents 
      // of the searched paragraph. 
      $('#DivToReplace').html(result); 
     }, 
     error: function(req, status, error) { 
      alert('error' + error); 
     } 
    }); 

Auch hier sollte die SetSelectedContent Lage sein, die Datenbank durch die params nur filtern - es sollte eigentlich nicht die gesamte Tabelle von materialisieren müssen Bücher, so Sessioning oder Caching fügt nur eine zusätzliche Ebene der Komplexität.

+0

danke dafür. Während dies mir hilft zu verstehen, dass das Web statuslos ist und ich nicht mehr auf das Viewmodel zugreifen kann, möchte ich _service.GetBooks nicht mehr aufrufen. Vielleicht ist die Lösung wirklich etwas Caching in _service zu implementieren. – majid

+0

Eine bessere Frage, die Sie hier stellen können, ist, was genau Sie mit IEnumerable tun? Zeigen Sie ganze Bücher gleichzeitig an? Zeigen Sie nur eine Liste von Buchnamen an? Was genau machst du mit den Daten, die es so teuer machen, wieder für jede Anfrage zu ziehen? Es gibt Möglichkeiten, wie Sie das, was Sie hier aus der Datenbank ziehen, reduzieren können. – Leniency

+0

In derselben Ansicht zeige ich Verse aus dem Buch an und gebe Benutzern die Möglichkeit, Kommentare zu einem bestimmten Vers/Absatz hinzuzufügen, alle Kommentare zu verbergen oder anzuzeigen, die in der iEnumerable Liste gespeichert sind. – majid

0

Wenn Sie einen Blick auf einen Benutzer-Browser senden Sie eine Instanz des Modells erstellen (in Ihrem Fall rufen Sie es Ansichtsmodell). Dies geschieht als Teil einer Aktion, die eine Ansicht in Ihrem Controller zurückgibt. Wenn Sie eine modifizierte Version von Ihnen Modellen wollen Aktions-Prozession rekonstruiert werden, sollten Sie es als Parameter in Ihnen Unterschrift im Fall eines Formulars Aktion beantragen POST einreichen, oder Sie gerade ein neues Modell erstellen und initialisieren Ansicht mit ihm.

Von dem, was ich sehe, ist dies der Fall. Erstellen Sie einfach einen neuen BooksViewModel, führen Sie eine Filterung durch und senden Sie einen View(myFilteredModel) an einen Benutzer.

Sie können aber auch versuchen, diese:

[HttpPost]  
public void SetContent(int chapterId, int paragraphId, BooksViewModel booksViewModel) 
    { 
     var paragraph = booksViewModel.Books.Where(b =>b.ChapterId == chapterId).First().Chapter.Paragraphs.Where(p => p.Id == paragraphId).First() 
     model.CurrentParagraph = paragraph; 
    } 

Wie für DB-Zugriff pro Aktion Ausführung - wird dies über die Implementierung eines Cache-Mechanismus gelöst. Denken Sie daran,

+0

Ja in meiner Controller-Methode, die die Ansicht erstellt Ich sende das Modell an die Ansicht, aber wie greife ich auf das gleiche Modell in zukünftigen Aufrufen von Controller-Methoden – majid

+0

Ich könnte das tun, aber das würde bedeuten, ich habe einen Aufruf an die Datenbank und neu zu füllen alle "Bücher" in der neuen Instanz von BooksViewModel. Ich möchte diesen zusätzlichen Datenbankanruf vermeiden, da er eine große Datenmenge zurückgeben könnte. – majid

+0

Das gleiche Modell - nur wenn Sie es zurück auf den Server posten. Sie greifen auf die gewünschten Parameter 'int chapterId, int paragraphId' zu und erstellen einfach eine neue. Wenn Sie einen Ajax-Weg wollen, nur einen Filter zu machen - Sie müssen einen Ajax-Aufruf zu Ihrer Aktion von Javascript initialisieren, und basierend auf der Antwort aktualisieren Sie einfach die Seite. Wenn Sie zu einer anderen Aktion wechseln, entfernen Sie sich von der Ansicht. –