2012-03-27 230 views
0

我很疑惑如何在MVC3中更新我的視圖模型。我正在試圖做的按鈕點擊搜索我的viewmodel特定的列表項。例如:從視圖更新模型

BooksViewModel 

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

在我看來,當一個用戶點擊按鈕我需要搜索列表的視圖模型是這樣的:

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

我遇到的問題是,我不能訪問實例來自控制器的BooksViewModel。如何訪問視圖正在使用的視圖模型實例,該實例已經具有從數據庫中檢索的數據?或者我對這一切都錯了?

由於事先

編輯

格言建議在我的模型通過從視圖到二次呼叫到控制器(即篩選模型)

,我會做到這一點的使用@Model這樣的關鍵字:

$.ajax({ 
      type: "POST", 
      url: "/Books/SetSelectedContent?id=" + id + "&paragraphId="+paragraphId+"&model="[email protected], // the URL of the controller action method 
      data: null, // optional data 
      success: function(result) { 

      }, 
      error: function(req, status, error) { 
       alert('error' + error); 
      } 
     }); 

當我試過這似乎ajax調用c在@Model上啓用

+0

是的,這會窒息 - 不能只是將整個模型追加到這樣的網址。它不知道如何將其轉換爲url編碼的字符串。 – Leniency 2012-03-27 16:37:38

回答

1

請記住,網頁和視圖是無狀態的。一旦行動執行,它就消失了(除非你會議的事情,但這是一個不同的野獸)。

如果您想在列表傳遞到視圖後搜索列表,請在不同的控制器操作(全新請求,前一個請求中的所有內容都不存在)中進行操作,那麼您必須重新創建列表。

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

下面是阿賈克斯樣本修正:

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

再次,SetSelectedContent應該能夠僅僅通過PARAMS篩選數據庫 - 它不應該有實際兌現的整個表書籍,所以會話或緩存只是增加了一層額外的複雜性。

+0

謝謝你。雖然這確實幫助我理解Web是無狀態的,但我無法再從索引訪問視圖模型,但我真的不想再次調用_service.GetBooks。也許解決方案是真的在_service中實現一些緩存。 – majid 2012-03-27 16:37:54

+0

在這裏問一個更好的問題是你在做什麼IEnumerable ?你是否一次顯示整本書?你只是顯示一個書名列表?你對數據做了什麼,使得每次請求再次拉動都很昂貴?有幾種方法可以減少你在這裏從數據庫中提取的內容。 – Leniency 2012-03-27 16:45:17

+0

在同一視圖中,我顯示的是書中的經文,並允許用戶在特定的詩句/段落上添加評論,隱藏或顯示存儲在模型中存儲的iEnumerable 列表中的所有評論 – majid 2012-03-27 16:54:53

0

當您向用戶瀏覽器發送視圖時,將創建模型的實例(在您的情況下稱爲ViewModel)。這是作爲某個Action的一部分完成的,該Action在Controller中返回一個視圖。如果您希望爲您的Action-procession重構您的Model的修改版本,則應該將其作爲參數請求,以便在您提交表單POST時使用Action的簽名,或者您只需創建一個新模型並使用它初始化View。

從我看到的情況來看。只需創建一個新的BooksViewModel,執行過濾並將View(myFilteredModel)發送給用戶。

但你也可以試試這個:

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

對於每個動作執行DB訪問 - 這是通過實現緩存機制來解決。

+0

是在我的控制器創建視圖的方法我發送模型到視圖,但我如何訪問同一模型在將來調用控制器方法 – majid 2012-03-27 16:11:41

+0

我可以這樣做,但這將意味着我已撥打數據庫和重新填充BooksViewModel新實例中的所有「書籍」。我想避免進行額外的數據庫調用,因爲它可能會返回大量的數據。 – majid 2012-03-27 16:17:14

+0

相同的型號 - 只有當您將其發回服務器。您可以訪問所需的參數'int chapterId,int paragraphId'並創建一個新的參數。如果你想要一個只是做一個過濾器的ajax方法 - 你需要從javascript初始化ajax調用你的動作,並根據響應更新頁面。轉向不同的行動意味着你正在遠離視野。 – 2012-03-27 16:19:23