【问题标题】:MVC Form Submit - Redirecting to an action that is not accessible from the browser directlyMVC 表单提交 - 重定向到浏览器无法直接访问的操作
【发布时间】:2012-02-03 00:43:30
【问题描述】:

我现在下班后正在学习 MVC 3,昨晚我遇到了一个看起来很容易解决的问题,但我似乎找不到解决方案。

我有一个简单的联系表格。最终用户填写表格并提交。当他们提交表单时,我将最终用户重定向到同一控制器中的不同操作,该操作呈现“查询提交”页面/视图,基本上是“感谢页面”。

控制器是这样设置的。

public ActionResult ContactUs()
{
   return View();
}

[HttpPost]
public ActionResult ContactUs(ContactInfo contactInfo)
{
     if (!ModelState.IsValid)
     {
          return View();
     }

     //perform some business logic

     return RedirectToAction("InquirySubmitted",contactInfo);


}

 public ActionResult InquirySubmitted(ContactInfo contactInfo)
 {
    return View(contactInfo);
 }

问题: 我不希望最终用户通过浏览器直接导航到 InquirySubmitted 操作。
我只希望控制器中的 ContactUs 操作能够将用户发送到 InquirySubmitted 视图。

我试图将 InquirySubmitted 操作设为私有,以便只有控制器可以这样调用它:

private ActionResult InquirySubmitted(ContactInfo contactInfo)

但这会产生一个我完全理解的错误,因为我强制浏览器使用 RedirectToAction() 请求 InquirySubmitted。

所以我的问题很简单:这个问题的最佳“MVC 3 风格”解决方案是什么。

【问题讨论】:

  • @Splash-X - 这是他可以做的一种选择,但如果用户出于某种原因刷新页面,它将重新提交联系请求。您通常会使用 Post-Redirect-Get 模式来解决这个问题。
  • @Splash-X 是的,该解决方案在技术上确实有效,谢谢。这是一个选项。但是正如神秘人所说,按 F5 会导致刷新,这会再次触发我所有的业务逻辑,正如他所说,这个解决方案打破了 PRG 模式,所以我希望有一个更理想的解决方案。截至目前,我看到的唯一解决方案是下面发布的答案,该答案是使用会话来查看最终用户是否来自联系页面,如果他们尝试直接访问 InquirySubmitted,则如果没有将他们发送回该页面。此解决方案与 Web 表单解决方案相同。
  • @Matt 我同意,但您的要求是最终用户无法请求 URL。通过创建操作,他们始终可以请求 URL。 Ek0nomik 是对的,您可以使用会话变量来跟踪他们是否应该能够查看页面。您还可以查看引用 URL 并检查它是否是表单页面,如果是,则显示视图,否则返回重定向到表单。

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


【解决方案1】:

您需要在 InquirySubmitted ActionResult 中添加逻辑,以防止用户在不应该查看页面时查看页面。

您已经将 InquirySubmitted 方法传递给您的模型 (ContactInfo)。您能否简单地检查传递给该方法的数据,如果不存在则将用户重定向到错误页面(或您选择的其他页面)?

另一种解决方案是在会话中设置一个布尔值,指示用户完成了“ContactUs”表单。然后您可以在 InquirySubmitted 中检查该会话对象。

【讨论】:

  • 是的,谢谢您的回答。是的,我可以肯定地做到这一点,这会奏效。但是,我只是想知道是否有我缺少的“MVC 3 特定功能”可以处理这个问题,而不必在会话中插入跟踪数据。
  • @Matt - 你需要它有多安全?我检查ContactInfo 模型的其他建议也可以。但是,该模型实际上只是归结为 GET 参数,因此可以伪造。
  • 此解决方案与您在 Web 表单应用程序中使用的解决方案相同,但似乎仍然是最好的。有效且简单。公共 ActionResult InquirySubmitted(ContactInfo contactInfo) { if (Session["ContactFormSubmitted"] == "true") { Session["ContactFormSubmitted"] = "false";返回视图(联系人信息); } 否则返回 RedirectToAction("ContactUs"); }
  • 您应该使用 TempData。 TempData 是一个专门的集合,它(开箱即用)依赖于 Session 但只保留键/值对直到它被读取一次。非常适合需要序列但将被重定向到的消息、向导导航和其他页面。只需在重定向到操作之前将一些变量推入 TempData 中,然后在另一个操作中从 TempData 中读取它。
【解决方案2】:

首先,我不得不说.. 谁在乎是否有人可以直接导航到查询提交页面?是否有任何机密信息或敏感信息?如果不是,那又如何?有什么痛吗?

但是,如果您决心这样做。 “如何使操作不能直接从浏览器访问”的问题的答案是,您可以简单地使用 Html.Action() 呈现页面,然后使用 [ChildActionOnly] 属性装饰操作方法。

但这实际上并不能解决问题,因为间接访问该操作只会回答您的问题,而不是解决您的问题。最终,您需要将用户重定向到一个 url 以加载页面,因此您将需要一些逻辑来确定他们是否可以查看该页面。这是

【讨论】:

    【解决方案3】:

    不确定这是否仍然适用于 MVC3,但在 MVC2 中有效。

    您的 global.asax 文件中包含您的 url 结构。您可以将您的 InquirySubmitted 添加到那里无法访问的 url 列表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 2016-08-21
      相关资源
      最近更新 更多