如何防止直接调用操作方法?

时间:2010-10-06 10:42:20

标签: asp.net-mvc

我正在开发MVC2中的向导类型解决方案,我想阻止用户直接进入第2步,但是,我仍然希望它显示在URL中。

另外,由于可以随时保存进度,我仍然希望能够以编程方式转到Step2。我怎么能这样做?

[HttpGet]
        public ActionResult Step1() {

            return View("Step1View");
        }

        [HttpPost]
        public ActionResult Step1(Stuff s) {

            return RedirectToAction("Step2", new { S = s });
        }

        [HttpGet] //<-- how do I stop users going directly here
        public ActionResult Step2(Stuff s) {


            return View();
        }

        [HttpPost]
        public ActionResult Step2(Stuff2 s) {


            return RedirectToAction("Step3");
        }

3 个答案:

答案 0 :(得分:2)

我自己没有尝试过,但如果我这样做,我会考虑一下ActionFilters。我将创建一些描述向导数据的上下文对象以及该向导的步骤(可能以某种方式包装一两个模型)。

这个向导上下文可以自我“验证”,因为我可以问下一个有效步骤是什么。

然后,通过它,我从动作过滤器加载它,然后如果当前动作对该步骤无效,我重定向。

当然,我可以在没有动作过滤器的情况下做到这一点,只需将其作为我正在查看的方法的前导。就个人而言,我先做这个,然后玩动作过滤器试着让它看起来有点整洁,如果我有时间的话。

答案 1 :(得分:1)

动作过滤器是最佳选择

首先,这将在很大程度上取决于临时保存数据的存储系统。操作过滤器应检查此存储,并查看步骤1数据是否存在。如果不是,您可以随时向ModelState添加错误,从而使其无效。因此,您的第2步代码如下所示:

[HttpGet]
[CheckExistingData]
public ActionResult Step2(Stuff s)
{
    if (!this.ModelState.IsValid)
    {
        return RedirectToAction("Step1");
    }
    return View(s);
}

因此。您的过滤器应检查现有数据,并且:

  • 填写Stuff参数或
  • 添加模型状态错误并保持参数为空

数据合并

您编写重定向到操作(在步骤1 POST中)以提供复杂对象的方式并不是一种好方法。您应该整合数据存储,因此无论您的用户来到第2步,过滤器始终都会起作用。在第1步POST中,您应该将数据保存到此特定存储,然后重定向到第2步。

您有两种进入第2步的方案:

  1. 从第1步开始
  2. 保存数据后的任何地方
  3. 这样,您的第2步对两种情况都会起作用。您可以在向导中创建任意数量的步骤,同样的过程仍然可以正常工作。

答案 2 :(得分:1)

我已经完成了一个高度可重复使用的向导,只需这样做:

return Navigate();

从操作中,向导知道该怎么做(如果实现向导模式,这是可能的)。 Navigate()是在基础WizardController类上定义的方法。

这个工作的原因是,实质上,步骤信息被序列化到每个请求的页面(AJAX与否),并在控制器在OnActionExecuting方法中读取响应时反序列化。

框架使用WizardStep属性来了解哪个操作对应于哪个向导步骤,并且控制器使用WizardOptions属性进行修饰,该属性指示向导将如何允许自己导航。 EG:

    [WizardStepOptions(WizardNavigatorRules.LeapBackOnly, WizardButtonRules.Both, WizardCompleteRules.DisableNavigation)]
    public class MembershipFormController : WizardController<ESregister.Models.TheSociety.RegistrationData>
    {
        [WizardStep(1, "Start")]
        public override ActionResult Start()
        {
            return Navigate();
        }

它是一个梦想。如果在使用向导的过程中,您需要修剪或添加步骤,您只需使用Range属性定义要显示的步骤,也可以在基类WizardController上定义:

        [WizardStep(2, "Category")]
        public ActionResult Category()
        {
            return Navigate();            
        }

        [HttpPost]
        public ActionResult Category(int ? Category)
        {
            if (Category == null)
            {
                ModelState.AddModelError("Category", "You must fill in a Category!");
                return Navigate();
            }
            if (Category == 3)
            {
                Range = new List<int> { 1, 2, 7, 8 };
            }
            else
            {
                Range = DefaultRange();
            }
            return Navigate();
        }

向导框架自动实现PRG。您只需要在上述情况下提供HttpPost,例如,根据用户输入修剪步骤范围。

它还提供如下导航控件:

<% StepManager stepManager = (StepManager)TempData["stepManager"];
   Html.WizardNavigator(stepManager);  %>
   Html.WizardButtons(stepManager, WizardButtonLocation.Top); %>

WizardNavigator显示/提供指向不同步骤的链接(如果允许则链接),WizardButtons是Start,Next,Continue,Previous和Confirm按钮。

它正在制作中。

我已经包含了所有这些细节,以显示可能的内容以及建议的解决方案是否有效。