我对如何在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 + "¶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上被阻塞
答案 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访问 - 这是通过实现缓存机制来解决的。