从视图更新模型
我很疑惑如何在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 + "¶graphId="+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上启用
请记住,网页和视图是无状态的。一旦行动执行,它就消失了(除非你会议的事情,但这是一个不同的野兽)。
如果您想在列表传递到视图后搜索列表,请在不同的控制器操作(全新请求,前一个请求中的所有内容都不存在)中进行操作,那么您必须重新创建列表。
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筛选数据库 - 它不应该有实际兑现的整个表书籍,所以会话或缓存只是增加了一层额外的复杂性。
谢谢你。虽然这确实帮助我理解Web是无状态的,但我无法再从索引访问视图模型,但我真的不想再次调用_service.GetBooks。也许解决方案是真的在_service中实现一些缓存。 – majid 2012-03-27 16:37:54
在这里问一个更好的问题是你在做什么IEnumerable
在同一视图中,我显示的是书中的经文,并允许用户在特定的诗句/段落上添加评论,隐藏或显示存储在模型中存储的iEnumerable
当您向用户浏览器发送视图时,将创建模型的实例(在您的情况下称为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访问 - 这是通过实现缓存机制来解决。
是在我的控制器创建视图的方法我发送模型到视图,但我如何访问同一模型在将来调用控制器方法 – majid 2012-03-27 16:11:41
我可以这样做,但这将意味着我已拨打数据库和重新填充BooksViewModel新实例中的所有“书籍”。我想避免进行额外的数据库调用,因为它可能会返回大量的数据。 – majid 2012-03-27 16:17:14
相同的型号 - 只有当您将其发回服务器。您可以访问所需的参数'int chapterId,int paragraphId'并创建一个新的参数。如果你想要一个只是做一个过滤器的ajax方法 - 你需要从javascript初始化ajax调用你的动作,并根据响应更新页面。转向不同的行动意味着你正在远离视野。 – 2012-03-27 16:19:23
是的,这会窒息 - 不能只是将整个模型追加到这样的网址。它不知道如何将其转换为url编码的字符串。 – Leniency 2012-03-27 16:37:38