阻止用户明确转到MVC页面

时间:2014-03-04 21:28:24

标签: asp.net-mvc asp.net-mvc-routing asp.net-mvc-controller

如何阻止用户在MVC中手动键入页面的URL?

例如,我有一个返回错误视图的控​​制器方法:

    // GET: /Checkout/Error
    public ActionResult Error()
    {
        return View("Error")
    }

编辑:以及返回成功视图的控制器方法:

        // GET: /Checkout/Complete
    public ActionResult Complete()
    {
        var order = /* get the order */
        return View("Complete", order)
    }

如果订单流程出现问题,我会重定向到它:

    public ActionResult Submit()
    {

        if (/*order succeeds*/) {
            return RedirectToAction("Complete");
        }
        else
            return RedirectToAction("Error");
    }

但是,用户可以手动输入“www.mysite.com/Checkout/Error”并在结帐工作流程的上下文之外获取错误视图。

我做了一些环顾四周并找到了ChildActionOnly,但这似乎只适用于从视图中调用操作,这里不适用。

我想我可以在错误操作方法的开头手动检查以查看订单是否确实存在问题,并在这种情况下返回错误视图,否则重定向用户,但似乎有必要是一种更简单的方法来阻止用户手动导航到这样的页面。

编辑:这同样适用于完成的视图。用户可以键入与该操作对应的URL。如何防止像这样调用此操作?

1 个答案:

答案 0 :(得分:3)

您可以从控制器中删除错误操作方法(但仍然保留视图)并使用return View()而不是RedirectToAction。在这种情况下,您的网址与RedirectToAction不同,其中 302响应告诉浏览器向Error操作方法发出新的GET请求。

public ActionResult Submit()
{
    if (/*order succeeds*/)
    {
        return RedirectToAction("Complete");
    }
    else
    {
        // TO DO : LOG ERROR
        return View("Error");
    }
}

假设您在~/Views/CurrentControllerName/~/Views/Shared

中有一个名为Error的视图

如果您的视图位于其他目录中,则可以提供该目录的完整路径。

return View("~/Views/MyErrors/OrderError.cshtml");

如果需要,您可以将一些信息传递给错误视图。

编辑:根据评论。

如果要将订单对象传递到完整视图,可以使用TempData传递订单对象。在“已完成”操作方法中,您可以检查特定TempData值是否可用,如果是,则显示正确的视图,否则告诉用户他们正在尝试访问不存在的页面/或任何其他相关消息/视图。

public ActionResult Submit()
{
    if (/*order succeeds*/)
    {
         // assuming newOrderId stores the Id of new order somehave.
        OrderVM orderVM=GetOrderFromSomeWhere(newOrderId);
        TempData["NewOrder"] =orderVM;
        return RedirectToAction("Complete");
    }
    else
    {
        // TO DO : LOG ERROR
        return View("Error");
    }
}

并在您的Complete操作方法中,检查您的TempData中是否有内容,然后向用户显示相应的视图。

public ActionResult Complete()
{      
  var model=TempData["NewOrder"] as OrderVM;
  if(model!=null)
  {
     return View(model);
  }
  return View("NotFound");
}

TempData使用场景后面的Session对象来存储数据。 TempData意味着一个非常短暂的实例,您只应在当前和后续请求中使用它!

Rachel编写了一个nice blog post来解释何时使用TempData / ViewData。值得一读。