-1

I am creating a web application where there are five steps. Home Page1 Page 2 Review Confirmation. In the url, it goes like localhost:22112/Home/Page1 Page 2 and so forth. My problem is if someone copies localhost:22112/Home/Page2, then it skips everything and jumps to page 2 directly. So, how can I stop that? I did the following but its not working properly. Any suggestions would be really helpful.

In the controller

 private bool IsFromIndexPage()
    {
        if (Session["IsFromIndex"] != null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

And for each page actionresult, I am writing it like this.

   [HttpGet]
    public ActionResult Page1()
    {   
  if (!IsFromIndexPage())
        {
            return RedirectToAction("Index");
        } 
    .....other methods..
    }  

    [HttpPost]
    public ActionResult Page1(Information model, string command)
    {   
  if (!IsFromIndexPage())
        {
            return RedirectToAction("Index");
        } 
    .....other methods..
    }  

  [HttpGet]
    public ActionResult Page2()
    {   
  if (!IsFromIndexPage())
        {
            return RedirectToAction("Index");
        } 
    .....other methods..
    }  

    [HttpPost]
    public ActionResult Page2(Information model, string command)
    {   
  if (!IsFromIndexPage())
        {
            return RedirectToAction("Index");
        } 
    .....other methods..
    }  
user2908229
  • 265
  • 1
  • 2
  • 11

2 Answers2

0

If you're using session to store the progress through the steps you should be checking your session variables to validate the request is for the given page otherwise redirect the user to the first/current completed page.

You can write a custom request handler for this to keep your session validation code separate your controller code

see this Question about how to implement the basic functionality to what you want to do

EDIT:

switch(currentStep){
   case 1:
     return Step1(model)
       break;
   case 2:
     return Step2(model)
       break;
   default:
       return new HttpNotFoundResult();
       break; 
}
Community
  • 1
  • 1
Chris McGrath
  • 1,727
  • 3
  • 19
  • 45
  • I am using the sql server session and creating session for each page like page 1 and page 2 where I am taking inputs. If possible, what would be the approach to hide the url completely and just show the name of the site and hiding the steps so that people can't jump pages?? So, it will be abc.com the whole time during all the steps. – user2908229 Oct 22 '13 at 18:46
  • the way i would approach it would be to check what stage of completion and write a private method for each step that returns an actionresult but this can get complicated if you are using a strongly typed model and the model changes each step if you can manage to keep your model the same its easy to simply use this pattern ie switch(currentStep){ case 1: return Step1(model) break; case 2: return Step2(model) break; default: return new HttpNotFoundResult(); break; } etc..etc.. – Chris McGrath Oct 22 '13 at 21:02
  • this wizard tutorial may be worth taking a look at as well http://afana.me/post/create-wizard-in-aspnet-mvc-3.aspx – Chris McGrath Oct 22 '13 at 21:16
0

Here is a bit different approach, on how to make a wizard with asp.net MVC using ajax.

Your url will be /Home/Wizard on every step. Since using the AjaxOnly attribute, it will not be possible to visit Step1, Step2 etc (see reference in the bottom for AjaxOnly)

Controller:

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

[AjaxOnly]
public ActionResult Step1()
{
    return PartialView("Step1");
}

[AjaxOnly]
public PartialViewResult Step2(FormCollection coll)
{
    Session["FullName"] = coll["FullName"]!= null ? coll["FullName"].ToString() : string.Empty;
    return PartialView("Step2");
}

[AjaxOnly]
public PartialViewResult Confirm(FormCollection coll)
{
    WizardModel model = new WizardModel() { Name = Session["FullName"].ToString(), Phone = coll["Phone"] != null ? coll["Phone"].ToString() : string.Empty };
    return PartialView("Confirm", model);
}

Model for last step:

public class WizardModel
{
    public string Phone { get; set; }
    public string Name { get; set; }
}

Make sure you reference jquery.unobtrusive-ajax in your page/layout page

<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>

Wizard.cshtml

@{
    ViewBag.Title = "Wizard";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Wizard - Overview</h2>
@using (Ajax.BeginForm("Step1", new AjaxOptions { HttpMethod="Get", UpdateTargetId = "wizardcontainer" }))
{
    <input type="submit" value="Start wizard" />
}
<div id="wizardcontainer"></div>

Step1.cshtml

<div>
    <h2>Wizard - Step 1</h2>
    <br />
    @using(Ajax.BeginForm("Step2", new AjaxOptions { UpdateTargetId = "wizardcontainer" }))
    { 
        @Html.Label("FullName")
        @Html.TextBox("FullName")
        <input type="submit" value="Next >>" />
    }
</div>

Step2.cshtml

<div>
    <h2>Wizard - Step 2</h2>
    @using(Ajax.BeginForm("Confirm", new AjaxOptions { UpdateTargetId = "wizardcontainer" }))
    { 
        @Html.Label("Phone")
        @Html.TextBox("Phone")
        @Ajax.ActionLink("<< Previous", "Step1", new AjaxOptions { UpdateTargetId = "wizardcontainer" })
        <input type="submit" value="Next >>" />
    }
</div>

Confirm.cshtml

@model MvcApplication2.Controllers.WizardModel
<div>
    <h2>Wizard - Final Stage</h2>
    Name: @Model.Name
    <br />
    Phone: @Model.Phone
    @Ajax.ActionLink("<< Previous", "Step2", new AjaxOptions { UpdateTargetId = "wizardcontainer" })
</div>

Look here for the AjaxOnly attribute: http://helios.ca/2009/05/27/aspnet-mvc-action-filter-ajax-only-attribute/

Lars Anundskås
  • 1,345
  • 10
  • 24