Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 从视图更新模型_Asp.net Mvc 3 - Fatal编程技术网

Asp.net mvc 3 从视图更新模型

Asp.net mvc 3 从视图更新模型,asp.net-mvc-3,Asp.net Mvc 3,我对如何在MVC3中更新viewmodel感到困惑。我试图在按钮上执行的操作单击搜索我的viewmodel以查找特定列表项。例如: BooksViewModel public List<Book> Books{get;set;} 我遇到的问题是,我无法从控制器访问BookViewModel的实例。如何访问视图正在使用的、已包含从数据库检索的数据的viewmodel实例?还是我完全错了 提前谢谢 编辑 maxim建议将我的模型从视图传递到控制器的辅助调用(即过滤模型) 我是否可以使

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

BooksViewModel

public List<Book> Books{get;set;}
我遇到的问题是,我无法从控制器访问BookViewModel的实例。如何访问视图正在使用的、已包含从数据库检索的数据的viewmodel实例?还是我完全错了

提前谢谢

编辑

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

我是否可以使用@Model关键字这样做:

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;
}
$.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阻塞了。当您向用户浏览器发送视图时,您创建了一个模型实例(在您的示例中,您称之为ViewModel)。这是作为在控制器中返回视图的某个操作的一部分完成的。如果您希望为动作处理重建模型的修改版本,则在表单
POST
submit的情况下,应将其作为动作签名中的参数进行请求,或者仅创建一个新模型并使用它初始化视图

据我所见,情况就是这样。只需创建一个新的
BooksViewModel
,进行筛选,然后向用户发送
视图(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访问,这可以通过实现缓存机制来解决

请记住,web和视图是无状态的。一旦动作被执行,它就消失了(除非你处理了一些事情,但那是另一个野兽)

如果要在列表传递到视图后,在不同的控制器操作(全新的请求,前一个请求中的所有内容都已消失)中搜索列表,则必须重新创建列表

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

是的,在创建视图的控制器方法中,我将模型发送到视图,但如何在将来调用控制器方法时访问同一模型我可以这样做,但这意味着我必须调用数据库并重新填充所有“书籍”在BooksViewModel的新实例中。我希望避免进行这个额外的数据库调用,因为它可能会返回大量数据。相同的模型-只有当您将其发回服务器时。您可以访问所需的参数
int chapterId,int paragraphId
,然后创建一个新的参数。如果您想要一种ajax方式来进行过滤,那么您需要从javascript初始化对操作的ajax调用,并根据响应更新页面。移动到其他操作意味着您正在离开视图。请查看我的更新答案,并将模型发布到操作。请查看我针对您的建议提出的问题的更新。谢谢是的,这会让人窒息-不能像那样将整个模型附加到url。它不知道如何将其转换为url编码的字符串。谢谢。虽然这确实帮助我理解web是无状态的,我无法再从索引访问viewmodel,但我真的不想再次调用_service.GetBooks。也许解决方案真的是在_服务中实现一些缓存。这里要问的一个更好的问题是,你到底在用IEnumerable做什么?你要同时展示整本书吗?您只是在显示书名列表吗?您到底在对数据做什么,使得每次请求再次提取数据的成本如此高昂?这里有一些方法可以减少从数据库中提取的内容。在同一视图中,我显示了本书中的诗句,并使用户能够在特定诗句/段落上添加注释,隐藏或显示注释—所有这些都存储在模型中存储的iEnumerable列表中—这更有意义。因此,IEnumerable并不像名字所暗示的那样,实际上是一个书籍列表,而是一个单一书籍的诗句列表。不管是哪种方式,都可以通过Ajax查看注释和段落。您根本不必处理会话或缓存。数据库搜索一个段落不需要具体化每本书,只需要一个过滤过的段落。我从我的答案中删除了会话内容。清理了我的答案,只显示了调用的ajax操作。如果能真正看到你的模型是什么样子的话会很有帮助,所以我猜了一下。