小编典典

ASP.NET MVC和ViewState

ajax

现在,我已经看到了一些类似的问题,但这并不是我想要问的,因此,对于所有那些尖叫的重复对象,我深表歉意:)。

我几乎没有接触过ASP.NET MVC,但据我了解,没有ViewState / ControlState
…好。所以我的问题是,保留控件状态的替代方法是什么?我们是否回到老式的ASP,在这里我们可以通过创建具有控件状态或MVC的隐藏表单输入来模拟ASP.NET
ViewState / ControlState的功能,我们是否始终假设AJAX并保留所有客户端状态并制作AJAX来电更新?

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

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

不寻找:

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

我正在/正在寻找的是:

  • 一种仅在数据未反弹到控件时才保留回发状态的方法。以仅在初始页面加载时绑定网格(即仅在必要时重新绑定数据)的情况考虑WebForms。如前所述,我并不是想模仿WebForms,只是想知道MVC提供了什么机制。

阅读 320

收藏
2020-07-26

共1个答案

小编典典

该约定已经可用,无需花太多时间。技巧是根据传递到视图中的模型连接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使用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>

请注意,文本框和文本区域具有标题和正文的ID?现在,注意我是如何从View的Model对象设置值的?由于您传入了FormCollection(并且应将视图设置为使用FormCollection进行强类型键入),因此您现在可以访问它。或者,无需强力键入,您可以简单地使用ViewData
[“ Title”](我认为)。

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

现在,以上代码是使用FormCollection的最简单,最原始的形式。当您开始使用ViewModels而不是FormCollection时,事情会变得很有趣。您可以开始添加自己的Models
/ ViewModels验证,并使控制器自动冒出自定义验证错误。那是第二天的答案。

我建议使用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);
  }
}

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

<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之外的高级技术,并提供了多种外部工具来简化您的生活(CastleWindsor,Moq等)。

2020-07-26