【问题标题】:Is using tempdata validate method entry and pass info through multiple POSTs in the controller a bad practice? Alternatives?使用 tempdata 验证方法条目并通过控制器中的多个 POST 传递信息是一种不好的做法吗?备择方案?
【发布时间】:2012-07-12 15:54:13
【问题描述】:

首先,一些上下文:

在我的控制器中,我在成功的 HTTP POST 上返回 RedirectToAction。我使用 TempData 保留用户输入的模型数据,以便我重定向到的方法可以再次使用此输入数据。

示例: 1. 在搜索栏输入用户 ID。 2.点击按钮,进行POST,通过我的repository在数据库中找到用户,用户ID保存在TempData中,调用RedirectToAction("Edit")

TempData["user"] = searchViewModel.userID;
return RedirectToAction("Edit");
  1. 在Edit视图上进行编辑,点击commit按钮,用户信息保存在TempData中,调用RedirectToAction("Confirm");
  2. 在“确认”视图中显示所做的更改,单击“确认”,执行最终的 HTTP POST,并通过我的存储库服务进行更改。

这似乎运作良好。为了处理人们试图通过键入“../Edit/Confirm”来跳到地址栏中的页面,我在我的 Confirm 方法中进行了此检查:

if (TempData["editUserViewModel"] == null)
  return RedirectToActionPermanent("Edit");

这是处理地址栏输入的最佳方式吗?我也做 TempData.Keep("editUserViewModel") 以便刷新工作。这是处理刷新的最佳方式吗?

【问题讨论】:

    标签: c# .net asp.net-mvc asp.net-mvc-3


    【解决方案1】:

    对于从第 1 步到第 2 步,我建议改为参数化操作:

    1. 在搜索字段中输入用户 ID。
    2. 单击按钮,执行POST,通过我的存储库在数据库中找到用户
    3. 调用 RedirectToAction("Edit", new {UserId = foundUserId})

    此外,在搜索时,您可能不应该进行 POST。当您正在寻找信息而不是对其进行变异时,GET 就很好了。这在您使用 tempdata 的第一个地方完全避免了 PRG 模式,因为您执行的是 GET 而不是 POST。

    至于确认,还有另一种方法可以在没有临时数据的情况下执行此操作。与其重定向到您的确认操作,不如发布到它,并返回您的确认视图模型。只有在第二个 POST 之后,您才会点击 repos 并在 POST 之后通过 Redirect 和最后一个 Get 完成 PRG 模式。

    用户不应为您的确认操作执行任何类型的 GET,正如您的创可贴所看到的那样。因此,根本不允许获取。从编辑表单 POST 到确认操作,返回一个视图,然后从该视图 POST 到第二个 POST 操作方法。由于这些都是同一过程的一部分,因此在该过程完成(已更新存储库)之前,您不必处理重定向或临时数据。

    更新(回复 cmets)

    1.) 如果我删除 SearchUser 函数上的 [HttpPost] 属性,视图上的搜索按钮如何知道要调用什么?

    您的搜索按钮嵌套在<form> HTML 元素中。您需要将表单的方法更改为 GET。如果该属性不存在,我相信 POST 是默认值。您的搜索按钮将保持不变,但表单会将用户输入的输入作为 HTTP GET 请求而不是 HTTP POST 提交:

    <form method="GET">
        ...
        <input type="submit" value="Search" />
    </form>
    

    2.) 你能澄清删除重定向确认吗?我无法理解如何将重定向更改为 POST

    很难向刚开始 Web 开发的人解释这一点,但本质上,每个重定向始终是一个 HTTP GET 请求。这就是为什么您必须将数据放入会话(tempdata 使用会话)以便在无状态请求之间维护它的原因。

    基本上,这是您的工作流程:

    1. 用户输入搜索输入并点击提交
    2. (1) 中的搜索作为 GET 请求发送到某个操作方法,该方法返回一个视图。
    3. (2) 中返回的视图包含一个带有附加输入元素的&lt;form method="POST" action="/Users/StillNeedsConfirmationAction"&gt;。这是用于编辑数据的表单。
    4. 用户从 (3) 在表单视图中输入数据并点击提交。
    5. 您的 UsersController 上的操作方法 StillNeedsConfirmationAction 接受带有 viewmodel 对象的 HTTP POST。该操作不是重定向,而是简单地返回另一个视图,传递相同的视图模型对象。
    6. (5) 中返回的视图包含&lt;form method="POST" action="/Users/ConfirmAndUpdateAction"&gt;。它将为您之前的 POST 表单中的每个文本框或其他表单元素呈现隐藏的输入。
    7. 用户在第二个表单上点击提交以确认字段
    8. 您的 UsersController 上的操作方法 ConfirmAndUpdateAction 接受一个 HTTP POST,其视图模型对象与您的其他 POST 操作所做的相同。但是,这次它没有返回另一个视图,而是将数据保存在您的存储库中并重定向。

    【讨论】:

    • 很棒的帖子。问题: 1. 如果我在我的 SearchUser 函数上删除 [HttpPost] 属性,我的视图上的搜索按钮如何知道要调用什么?我对 MVC/Web 开发非常陌生,目前正在实习。 2.你能澄清删除重定向确认吗?我无法理解如何将重定向更改为 POST。
    • 我一直在研究。我应该将我的按钮更改为 Html.ActionLink()s 吗?
    • 不,请参阅我的更新答案。您的表单可以通过更改其 method 属性来发送 GET 请求。
    • 这很棒。我已经实现了很多改变。我担心的是地址栏 URL,返回 Views 并不会更改地址这一事实。当我单击编辑页面上的 POST 按钮时,它会将我带到“确认”视图,但地址 URL 仍显示“../edit”。此外,在搜索用户时,地址栏中会显示 userId 参数。这是一种安全的做法吗?
    • URL 未更改的原因可能是因为您将 ../edit 路由映射到了 2 个具有相同名称的操作,1 个 GET 和 1 个 POST。如果是这样,您可以通过将 Edit POST 操作重命名为其他内容(如 Confirm)来解决此问题,并将 Confirm POST 操作重命名为类似 Commit。然后,您将从搜索 GET 到编辑 GET、确认 POST、提交 POST。至于安全性,您的用户输入了 userId,因此他们知道它来自哪里。真正通过网络对其进行加密的唯一方法是使用 HTTPS/SSL。
    猜你喜欢
    • 1970-01-01
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多