从视图更新模型

时间:2012-03-27 16:04:47

标签: asp.net-mvc-3

我对如何在MVC3中更新我的viewmodel感到困惑。我试图在按钮上单击搜索我的viewmodel以查找特定列表项。例如:

BooksViewModel

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

在我看来,当用户点击按钮时,我需要在ViewModel中搜索List,如下所示:

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的实例。如何访问视图正在使用的已具有从数据库检索的数据的viewmodel实例?或者我说这一切都错了?

提前谢谢

修改

格言建议将我的模型从视图传递到控制器的辅助调用(即过滤模型)

我会通过使用@Model关键字这样做:

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

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

当我尝试这个时,似乎ajax调用在@Model上被阻塞

2 个答案:

答案 0 :(得分: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示例的修复:

$.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应该只能通过参数来过滤数据库 - 它不应该实际实现整个书籍表,因此会话或缓存只会增加额外的复杂性。

答案 1 :(得分:0)

当您向用户浏览器发送视图时,您将创建模型的实例(在您的情况下,您将其称为ViewModel)。这是作为一些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访问 - 这是通过实现缓存机制来解决的。