ASP.NET MVC和ViewState

nic*_*ine 17 viewstate ajax asp.net-mvc asp.net-mvc-2

现在我已经看到了这样的一些问题,但这并不是我想要问的问题,所以对于所有那些尖叫的复制品,我道歉:).

我几乎没有碰过ASP.NET MVC,但据我所知,没有ViewState/ControlState ......很好.所以我的问题是保留控件状态的替代方法是什么?我们是否可以回到旧学校ASP,在那里我们可以通过创建具有控件状态的隐藏表单输入来模拟ASP.NET ViewState/ControlState所做的事情,或者使用MVC,我们只是假设AJAX始终并保留所有状态客户端并制作AJAX要求更新?

这个问题有一些答案,在Asp.net mvc维护viewstate?,但不完全是我在答案中寻找的东西.

更新:感谢目前为止的所有答案.只是为了清理我不想要的东西和我正在寻找的东西:

不寻找:

  • 会话解决方案
  • Cookie解决方案
  • 不想在MVC中模仿WebForms

我在/正在寻找什么:

  • 如果数据没有反弹到控件,则仅在回发时保留状态的方法.认为WebForms的方案是仅在初始页面加载时绑定网格,即仅在必要时重新绑定数据.正如我所提到的,我并不是想模仿WebForms,只是想知道MVC提供了什么机制.

edu*_*911 16

该惯例已经可以使用而不会跳过太多的箍.诀窍是根据传递给视图的模型连接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);
  }
}
Run Code Online (Sandbox Code Playgroud)

接下来发生的是ViewEngine使用formCollection并使用Html帮助程序将集合中的键与视图中的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>
Run Code Online (Sandbox Code Playgroud)

请注意,textbox和textarea具有Title和Body的ID?现在,请注意我是如何设置View的Model对象的值的?由于您传入了FormCollection(并且您应该将视图设置为使用FormCollection进行强类型化),因此您现在可以访问它.或者,如果没有强类型,您可以简单地使用ViewData ["Title"](我认为).

POOF你神奇的ViewState.这个概念称为约定优于配置.

现在,上面的代码是使用FormCollection的最简单,最简单的形式.当您开始使用ViewModels而不是FormCollection时,事情变得有趣.您可以开始添加自己的Models/ViewModel验证,并让控制器自动冒泡自定义验证错误.这是另一天的答案.

我建议使用PostFormViewModel而不是Post对象,但是建议使用他自己的.无论哪种方式,通过在action方法上要求一个对象,您现在可以获得一个可以调用的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);
  }
}
Run Code Online (Sandbox Code Playgroud)

你的强类型视图需要调整:

<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>
Run Code Online (Sandbox Code Playgroud)

您可以更进一步,直接从您在控制器中设置的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>
Run Code Online (Sandbox Code Playgroud)

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

很多公约都没有了.我强烈推荐的一些书籍更详细地介绍了这些模式:

按照这个顺序,第一个包含整个MVC框架的原始细节.后者涵盖了微软官方以外的先进技术,有几种外部工具可以让您的生活更轻松(Castle Windsor,Moq等).

  • 很高兴看到他们来接受你的回答 (2认同)