Asp.net mvc 3 从视图更新模型
我对如何在MVC3中更新viewmodel感到困惑。我试图在按钮上执行的操作单击搜索我的viewmodel以查找特定列表项。例如: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建议将我的模型从视图传递到控制器的辅助调用(即过滤模型) 我是否可以使
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 + "¶graphId="+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操作。如果能真正看到你的模型是什么样子的话会很有帮助,所以我猜了一下。