1

EDIT AFTER:

I should have worded my original question better: In the example below, I am using two forms:

using (Html.BeginForm....

In the controller, how would I validate only one of the forms, and NOT the entire model? Is this even possible? Or, am I trying to use MVC in a way it's not intended? I've been an ASP.NET forms guy for many years. Still learning MVC.

// END EDIT

I have a single view with a form that I need to present as a two-part (or two-page) form. Both parts have some required fields. I am able to simulate the multi-page form alright, but what I'm having trouble with is the validation. With each post, it's validating all of the fields on the entire view. How would I get it to validate only the fields that are currently visible?

Here's what I have now (simplified):

Model:

public Boolean Page1Complete { get; set; }
public Boolean Page2Complete { get; set; }

[Required(ErrorMessageResourceType = typeof(Resources.CustomerSatisfactionSurvey), ErrorMessageResourceName = "Page1Question1Required")]
public int? LikelyToReturn { get; set; }

[Required(ErrorMessageResourceType = typeof(Resources.CustomerSatisfactionSurvey), ErrorMessageResourceName = "Page2Question1Required")]
public int? RecomendToFriend { get; set; }

View:

if (!Model.Page1Complete)
{
    using (Html.BeginForm("PatientSatisfactionSurveyPage1", "Forms", FormMethod.Post, new { id = "patient-satisfaction-survey-page-1", @class = "full-form" }))
    {
        @for (var a = 0; a < 11; a++)
        {
           @a - @Html.RadioButtonFor(model => Model.LikelyToReturn, @a)
        }
        <input type="submit" id="page1-submit" name="page1-submit" value="Continue" class="btn green2">
   }
}
else
// Page1 was submitted successfully. Display Page 2
{
    using (Html.BeginForm("PatientSatisfactionSurveyPage2", "Forms", FormMethod.Post, new { id = "patient-satisfaction-survey-page-2", @class = "full-form" }))
    {
        @for (var a = 0; a < 11; a++)
        {
           @a - @Html.RadioButtonFor(model => Model.RecomendToFriend, @a)
        }
        <input type="submit" id="page2-submit" name="page2-submit" value="Complete" class="btn green2">
    }
}

Controller:

[HttpPost]
public ActionResult PatientSatisfactionSurvey([Bind]PatientSatisfactionSurveyPage pss)
    {
        //Process and validate the first page
        if (Request.Form["page1-submit"] != null)
        {
            if (ModelState.IsValid)
            {
                pss.Page1Complete = true;
                // Page 1 Logic...
            }
        }

        //Process and validate the first page
        if (Request.Form["page2-submit"] != null)
        {
            if (ModelState.IsValid)
            {
                pss.Page2Complete = true;
                // Page 2 Logic...
            }
        }
    }
5
  • 2
    Why do you have to use the same action method ? Commented Jun 1, 2015 at 18:03
  • Lucas, I don't. I'm new to MVC. Been doing standard ASP.NET forms for many, many years. having trouble wrapping my head around how MVC all works. Can you show my how to use separate action methods, and how that would help solve my problem? Thanks! Commented Jun 1, 2015 at 18:05
  • is there something else I can add to my answer for make it as the best answer ? ( check button ) Commented Jun 1, 2015 at 18:39
  • Lucas, see my question below your answer. Commented Jun 1, 2015 at 19:05
  • 1
    You could always use a single form and validate individual controls or groups of controls as per this answer Commented Jun 1, 2015 at 22:14

1 Answer 1

3

There are many ways of doing it:

I tried to make the simplest

your controller:

  public class LikelyToReturnModel
  {
     [Required]
     public int LikelyToReturn { get; set; }
  }

  public class RecomendToFriendModel
  {
     public int LikelyToReturn { get; set; }

     [Required]
     public int RecomendToFriend { get; set; }
  }

  public class PatientSatisfactionController : Controller
  {
     //
     // GET: /PatientSatisfaction/
     public ActionResult LikelyToReturn()
     {
        return View(new LikelyToReturnModel());
     }

     [HttpPost]
     [ValidateAntiForgeryToken()]
     public ActionResult LikelyToReturn(LikelyToReturnModel model)
     {
        //validation example
        if (model.LikelyToReturn == 0)
        {
           ModelState.AddModelError("", "Can't be zero!!!");
        }
        if (ModelState.IsValid)
        {
           return RedirectToAction("RecomendToFriend", new { LikelyToReturn = model.LikelyToReturn });
        }
        return View(model);
     }

     public ActionResult RecomendToFriend(int LikelyToReturn)
     {
        return View(new RecomendToFriendModel { LikelyToReturn = LikelyToReturn });
     }

     [HttpPost]
     [ValidateAntiForgeryToken()]
     public ActionResult RecomendToFriend(RecomendToFriendModel model)
     {
        if (ModelState.IsValid)
        {
           //do something
        }
        return View(model);
     }

  }

your view LikelyToReturn:

  @model MVCApp.Controllers.LikelyToReturnModel
  <h2>LikelyToReturn</h2>
  @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "patient-satisfaction-survey-page-1", @class = "full-form" }))
  {
     @Html.ValidationSummary(true)
     @Html.AntiForgeryToken()

     for (var a = 0; a < 11; a++)
     {
        @Html.RadioButtonFor(model => Model.LikelyToReturn, a) @a <br />
     }
     <button type="submit">Continue</button>
  }

your view RecomendToFriend:

  @model MVCApp.Controllers.RecomendToFriendModel
  <h2>RecomendToFriend</h2>
  @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "patient-satisfaction-survey-page-2", @class = "full-form" }))
  {
     @Html.ValidationSummary(true)
     @Html.AntiForgeryToken()
     @Html.HiddenFor(_ => _.LikelyToReturn)

     for (var a = 0; a < 11; a++)
     {
        @Html.RadioButtonFor(model => Model.RecomendToFriend, a) @a <br />
     }
     <button type="submit">Complete</button>
  }
Sign up to request clarification or add additional context in comments.

2 Comments

Ok, this is making a lot of sense. Thanks Lucas. Just one question about splitting the view into two: How does the model work in this example? Is there no model? Or does each view have it's own model?
Each view declares its @model

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.