首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ASP.NET MVC和ViewState

ASP.NET MVC和ViewState
EN

Stack Overflow用户
提问于 2009-09-24 18:46:25
回答 7查看 13.8K关注 0票数 17

现在我已经看到了一些类似的问题,但这并不是我想要问的问题,所以对于所有这些尖叫重复的问题,我道歉:)。

我几乎没有接触到ViewState,但据我所知,没有ASP.NET /ControlState...很好。所以我的问题是,保留控件状态的替代方案是什么?我们是否要回到老派的ASP,我们可以通过创建带有控件状态的隐藏表单输入来模拟ASP.NET视图状态/控件状态所做的事情,或者使用MVC,我们只是假设AJAX总是保留客户端的所有状态并进行AJAX调用以进行更新吗?

这个问题有一些答案,Maintaining viewstate in Asp.net mvc?,但不完全是我想要的答案。

更新:感谢你到目前为止的所有答案。只是为了弄清楚我不想要的和我想要的:

不寻找:

  • Session solution
  • Cookie solution
  • 不想模仿MVC

中的WebForms

我正在/正在寻找的:

  • 如果数据未重新绑定到控件,则仅在回发时保留状态的方法。考虑WebForms的场景,只在初始页面加载时绑定网格,即只在必要时重新绑定数据。正如我提到的,我并不想模仿WebForms,只是想知道MVC提供了什么机制。
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-11-05 11:32:59

这个约定已经可以使用了,而不需要经历太多的困难。诀窍是根据传递到视图中的模型连接TextBox值。

[AcceptVerbs(HttpVerbs.Get)]   
public ActionResult CreatePost()
{
  return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreatePost(FormCollection formCollection)
{
  try
  {
    // do your logic here

    // maybe u want to stop and return the form
    return View(formCollection);
  }
  catch 
  {
    // this will pass the collection back to the ViewEngine
    return View(formCollection);
  }
}

接下来发生的是,ViewEngine使用helpers获取formCollection并将集合中的键与视图中的ID名称/值进行匹配。例如:

<div id="content">

  <% using (Html.BeginForm()) { %>

  Enter the Post Title: <%= Html.TextBox("Title", Model["Title"], 50) %><br />
  Enter the Post Body: <%= Html.TextArea("Body", Model["Body"]) %><br />

  <%= Html.SubmitButton() %>

  <% } %>

</div>

注意到文本框和文本区域的ID是Title和Body吗?现在,注意到我是如何从View的Model对象中设置值的吧?由于传入了一个FormCollection (并且应该使用FormCollection将视图设置为强类型),现在可以访问它了。或者,在没有强类型的情况下,您可以简单地使用ViewData"Title"

抛出你神奇的ViewState吧。这个概念被称为约定重于配置。

现在,上面的代码是使用FormCollection的最简单、最简单的形式。当您开始使用ViewModels而不是FormCollection时,事情就变得有趣了。您可以开始添加您自己的模型/视图模型的验证,并让控制器自动生成自定义验证错误。不过,这是另一天的答案。

我建议使用PostFormViewModel而不是Post对象,但是使用各自的对象。无论哪种方式,通过在操作方法上要求一个对象,您现在可以获得一个可以调用的IsValid()方法。

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreatePost(Post post)
{

  // errors should already be in the collection here
  if (false == ModelState.IsValid())
    return View(post);

  try
  {
    // do your logic here

    // maybe u want to stop and return the form
    return View(post);
  }
  catch 
  {
    // this will pass the collection back to the ViewEngine
    return View(post);
  }
}

并且您的强类型视图将需要调整:

<div id="content">

  <% using (Html.BeginForm()) { %>

  Enter the Post Title: <%= Html.TextBox("Title", Model.Title, 50) %><br />
  Enter the Post Body: <%= Html.TextArea("Body", Model.Body) %><br />

  <%= Html.SubmitButton() %>

  <% } %>

</div>

您可以更进一步,直接从您在控制器中设置的ModelState在视图中显示错误。

<div id="content">

  <%= Html.ValidationSummary() %>

  <% using (Html.BeginForm()) { %>

  Enter the Post Title: 
    <%= Html.TextBox("Title", Model.Title, 50) %>
    <%= Html.ValidationMessage("Title") %><br />

  Enter the Post Body: 
    <%= Html.TextArea("Body", Model.Body) %>
    <%= Html.ValidationMessage("Body") %><br />

  <%= Html.SubmitButton() %>

  <% } %>

</div>

这种方法的有趣之处在于,您会注意到,我没有设置验证摘要,也没有在视图中设置单个验证消息。我喜欢实践DDD概念,这意味着我的验证消息(和摘要)在我的域中控制,并以集合的形式传递。然后,我遍历集合(如果存在任何错误),并将它们添加到当前的ModelState.AddErrors集合中。其余的是在返回View(post)时自动完成的。

很多传统已经过时了。我强烈推荐的几本书更详细地介绍了这些模式,它们是:

按照这个顺序,第一部分涵盖了整个MVC框架的原始细节。后者涵盖了Microsoft官方relm之外的高级技术,以及几个让您的工作变得更容易的外部工具(Castle Windsor,Moq等)。

票数 16
EN

Stack Overflow用户

发布于 2009-09-24 18:57:58

视图在MVC模式中应该是哑巴的,只是显示控制器给它的东西(显然我们经常在那里得到一些逻辑,但前提是它不是),结果是,控件不负责它们的状态,它每次都来自控制器。

我不能推荐Steven Sanderson的书Pro来理解这个模式和它的这个实现。

票数 4
EN

Stack Overflow用户

发布于 2009-11-05 12:00:02

在Web窗体中,控件值在视图状态中维护,因此(理论上)不需要在每次回发时重新初始化。这些值(同样在理论上)由框架维护。

在ASP.NET MVC中,如果遵循该范例,则不需要维护表单元素的状态。表单元素值在post上可用,您的控制器可以对其执行操作(验证、数据库更新等)。对于处理完帖子后显示的任何表单元素,您(开发人员)负责初始化它们-框架不会自动为您做这件事。

也就是说,我读到过一种叫做TempData的机制,它允许你的控制器在重定向之后将数据传递给另一个控制器。它实际上是一个会话变量(或者cookie,如果您这样配置它的话),但是在下一个请求之后它会被自动清除。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1473483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档